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

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

Merge branch 's390-qeth-next'



Julian Wiedmann says:

====================
s390/qeth: updates 2019-01-25

please apply a first batch of qeth patches for net-next, primarily touching the
net_device parts of the driver.
In addition to the usual refactoring & code consolidation, patch 7 makes use of
netif_device_detach() to let the stack know when our control plane is down. This
helps quite a bit wrt to overall locking and proper init/shutdown sequencing.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents a118b19d 5fc692a7
Loading
Loading
Loading
Loading
+3 −11
Original line number Diff line number Diff line
@@ -741,11 +741,6 @@ struct qeth_discipline {
					struct qeth_ipa_cmd *cmd);
};

struct qeth_vlan_vid {
	struct list_head list;
	unsigned short vid;
};

enum qeth_addr_disposition {
	QETH_DISP_ADDR_DELETE = 0,
	QETH_DISP_ADDR_DO_NOTHING = 1,
@@ -792,8 +787,6 @@ struct qeth_card {
	wait_queue_head_t wait_q;
	spinlock_t mclock;
	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
	struct mutex vid_list_mutex;		/* vid_list */
	struct list_head vid_list;
	DECLARE_HASHTABLE(mac_htable, 4);
	DECLARE_HASHTABLE(ip_htable, 4);
	DECLARE_HASHTABLE(ip_mc_htable, 4);
@@ -802,7 +795,6 @@ struct qeth_card {
	unsigned long thread_start_mask;
	unsigned long thread_allowed_mask;
	unsigned long thread_running_mask;
	struct task_struct *recovery_task;
	spinlock_t ip_lock;
	struct qeth_ipato ipato;
	struct list_head cmd_waiter_list;
@@ -976,11 +968,8 @@ extern struct qeth_dbf_info qeth_dbf[QETH_DBF_INFOS];

struct net_device *qeth_clone_netdev(struct net_device *orig);
struct qeth_card *qeth_get_card_by_busid(char *bus_id);
void qeth_set_recovery_task(struct qeth_card *);
void qeth_clear_recovery_task(struct qeth_card *);
void qeth_set_allowed_threads(struct qeth_card *, unsigned long , int);
int qeth_threads_running(struct qeth_card *, unsigned long);
int qeth_wait_for_threads(struct qeth_card *, unsigned long);
int qeth_do_run_thread(struct qeth_card *, unsigned long);
void qeth_clear_thread_start_bit(struct qeth_card *, unsigned long);
void qeth_clear_thread_running_bit(struct qeth_card *, unsigned long);
@@ -1047,6 +1036,9 @@ netdev_features_t qeth_fix_features(struct net_device *, netdev_features_t);
netdev_features_t qeth_features_check(struct sk_buff *skb,
				      struct net_device *dev,
				      netdev_features_t features);
int qeth_open(struct net_device *dev);
int qeth_stop(struct net_device *dev);

int qeth_vm_request_mac(struct qeth_card *card);
int qeth_xmit(struct qeth_card *card, struct sk_buff *skb,
	      struct qeth_qdio_out_q *queue, int ipv, int cast_type,
+62 −70
Original line number Diff line number Diff line
@@ -193,23 +193,6 @@ const char *qeth_get_cardname_short(struct qeth_card *card)
	return "n/a";
}

void qeth_set_recovery_task(struct qeth_card *card)
{
	card->recovery_task = current;
}
EXPORT_SYMBOL_GPL(qeth_set_recovery_task);

void qeth_clear_recovery_task(struct qeth_card *card)
{
	card->recovery_task = NULL;
}
EXPORT_SYMBOL_GPL(qeth_clear_recovery_task);

static bool qeth_is_recovery_task(const struct qeth_card *card)
{
	return card->recovery_task == current;
}

void qeth_set_allowed_threads(struct qeth_card *card, unsigned long threads,
			 int clear_start_mask)
{
@@ -236,15 +219,6 @@ int qeth_threads_running(struct qeth_card *card, unsigned long threads)
}
EXPORT_SYMBOL_GPL(qeth_threads_running);

int qeth_wait_for_threads(struct qeth_card *card, unsigned long threads)
{
	if (qeth_is_recovery_task(card))
		return 0;
	return wait_event_interruptible(card->wait_q,
			qeth_threads_running(card, threads) == 0);
}
EXPORT_SYMBOL_GPL(qeth_wait_for_threads);

void qeth_clear_working_pool_list(struct qeth_card *card)
{
	struct qeth_buffer_pool_entry *pool_entry, *tmp;
@@ -1430,7 +1404,6 @@ static void qeth_setup_card(struct qeth_card *card)
	spin_lock_init(&card->thread_mask_lock);
	mutex_init(&card->conf_mutex);
	mutex_init(&card->discipline_mutex);
	mutex_init(&card->vid_list_mutex);
	INIT_WORK(&card->kernel_thread_starter, qeth_start_kernel_thread);
	INIT_LIST_HEAD(&card->cmd_waiter_list);
	init_waitqueue_head(&card->wait_q);
@@ -3558,8 +3531,6 @@ static void qeth_qdio_cq_handler(struct qeth_card *card, unsigned int qdio_err,
	card->qdio.c_q->next_buf_to_init = (card->qdio.c_q->next_buf_to_init
				   + count) % QDIO_MAX_BUFFERS_PER_Q;

	netif_wake_queue(card->dev);

	if (card->options.performance_stats) {
		int delta_t = qeth_get_micros();
		delta_t -= card->perf_stats.cq_start_time;
@@ -3928,7 +3899,6 @@ static int qeth_fill_buffer(struct qeth_qdio_out_q *queue,
{
	struct qdio_buffer *buffer = buf->buffer;
	bool is_first_elem = true;
	int flush_cnt = 0;

	__skb_queue_tail(&buf->skb_list, skb);

@@ -3949,24 +3919,22 @@ static int qeth_fill_buffer(struct qeth_qdio_out_q *queue,

	if (!queue->do_pack) {
		QETH_CARD_TEXT(queue->card, 6, "fillbfnp");
		/* set state to PRIMED -> will be flushed */
		atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
		flush_cnt = 1;
	} else {
		QETH_CARD_TEXT(queue->card, 6, "fillbfpa");
		if (queue->card->options.performance_stats)
			queue->card->perf_stats.skbs_sent_pack++;
		if (buf->next_element_to_fill >=
				QETH_MAX_BUFFER_ELEMENTS(queue->card)) {
			/*
			 * packed buffer if full -> set state PRIMED
			 * -> will be flushed
			 */
			atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
			flush_cnt = 1;
		}

		/* If the buffer still has free elements, keep using it. */
		if (buf->next_element_to_fill <
		    QETH_MAX_BUFFER_ELEMENTS(queue->card))
			return 0;
	}
	return flush_cnt;

	/* flush out the buffer */
	atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
	queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) %
				  QDIO_MAX_BUFFERS_PER_Q;
	return 1;
}

static int qeth_do_send_packet_fast(struct qeth_qdio_out_q *queue,
@@ -3982,7 +3950,6 @@ static int qeth_do_send_packet_fast(struct qeth_qdio_out_q *queue,
	 */
	if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY)
		return -EBUSY;
	queue->next_buf_to_fill = (index + 1) % QDIO_MAX_BUFFERS_PER_Q;
	qeth_fill_buffer(queue, buffer, skb, hdr, offset, hd_len);
	qeth_flush_buffers(queue, index, 1);
	return 0;
@@ -4040,10 +4007,9 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
			}
		}
	}
	tmp = qeth_fill_buffer(queue, buffer, skb, hdr, offset, hd_len);
	queue->next_buf_to_fill = (queue->next_buf_to_fill + tmp) %
				  QDIO_MAX_BUFFERS_PER_Q;
	flush_count += tmp;

	flush_count += qeth_fill_buffer(queue, buffer, skb, hdr, offset,
					hd_len);
	if (flush_count)
		qeth_flush_buffers(queue, start_index, flush_count);
	else if (!atomic_read(&queue->set_pci_flags_count))
@@ -5154,13 +5120,6 @@ int qeth_core_hardsetup_card(struct qeth_card *card, bool *carrier_ok)
		*carrier_ok = true;
	}

	if (qeth_netdev_is_registered(card->dev)) {
		if (*carrier_ok)
			netif_carrier_on(card->dev);
		else
			netif_carrier_off(card->dev);
	}

	card->options.ipa4.supported_funcs = 0;
	card->options.ipa6.supported_funcs = 0;
	card->options.adp.supported_funcs = 0;
@@ -5937,9 +5896,6 @@ int qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
	if (!card)
		return -ENODEV;

	if (!qeth_card_hw_is_reachable(card))
		return -ENODEV;

	if (card->info.type == QETH_CARD_TYPE_OSN)
		return -EPERM;

@@ -6250,8 +6206,6 @@ int qeth_core_ethtool_get_link_ksettings(struct net_device *netdev,
	/* Check if we can obtain more accurate information.	 */
	/* If QUERY_CARD_INFO command is not supported or fails, */
	/* just return the heuristics that was filled above.	 */
	if (!qeth_card_hw_is_reachable(card))
		return -ENODEV;
	rc = qeth_query_card_info(card, &carrier_info);
	if (rc == -EOPNOTSUPP) /* for old hardware, return heuristic */
		return 0;
@@ -6534,8 +6488,6 @@ static int qeth_set_ipa_rx_csum(struct qeth_card *card, bool on)
	return (rc_ipv6) ? rc_ipv6 : rc_ipv4;
}

#define QETH_HW_FEATURES (NETIF_F_RXCSUM | NETIF_F_IP_CSUM | NETIF_F_TSO | \
			  NETIF_F_IPV6_CSUM | NETIF_F_TSO6)
/**
 * qeth_enable_hw_features() - (Re-)Enable HW functions for device features
 * @dev:	a net_device
@@ -6545,17 +6497,20 @@ void qeth_enable_hw_features(struct net_device *dev)
	struct qeth_card *card = dev->ml_priv;
	netdev_features_t features;

	rtnl_lock();
	features = dev->features;
	/* force-off any feature that needs an IPA sequence.
	/* force-off any feature that might need an IPA sequence.
	 * netdev_update_features() will restart them.
	 */
	dev->features &= ~QETH_HW_FEATURES;
	dev->features &= ~dev->hw_features;
	/* toggle VLAN filter, so that VIDs are re-programmed: */
	if (IS_LAYER2(card) && IS_VM_NIC(card)) {
		dev->features &= ~NETIF_F_HW_VLAN_CTAG_FILTER;
		dev->wanted_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
	}
	netdev_update_features(dev);
	if (features != dev->features)
		dev_warn(&card->gdev->dev,
			 "Device recovery failed to restore all offload features\n");
	rtnl_unlock();
}
EXPORT_SYMBOL_GPL(qeth_enable_hw_features);

@@ -6624,10 +6579,7 @@ netdev_features_t qeth_fix_features(struct net_device *dev,
		features &= ~NETIF_F_TSO;
	if (!qeth_is_supported6(card, IPA_OUTBOUND_TSO))
		features &= ~NETIF_F_TSO6;
	/* if the card isn't up, remove features that require hw changes */
	if (card->state == CARD_STATE_DOWN ||
	    card->state == CARD_STATE_RECOVER)
		features &= ~QETH_HW_FEATURES;

	QETH_DBF_HEX(SETUP, 2, &features, sizeof(features));
	return features;
}
@@ -6659,6 +6611,46 @@ netdev_features_t qeth_features_check(struct sk_buff *skb,
}
EXPORT_SYMBOL_GPL(qeth_features_check);

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);
	local_bh_disable();
	napi_schedule(&card->napi);
	/* kick-start the NAPI softirq: */
	local_bh_enable();
	return 0;
}
EXPORT_SYMBOL_GPL(qeth_open);

int qeth_stop(struct net_device *dev)
{
	struct qeth_card *card = dev->ml_priv;

	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);

static int __init qeth_core_init(void)
{
	int rc;
+1 −0
Original line number Diff line number Diff line
@@ -81,6 +81,7 @@ enum qeth_card_types {

#define IS_IQD(card)	((card)->info.type == QETH_CARD_TYPE_IQD)
#define IS_OSD(card)	((card)->info.type == QETH_CARD_TYPE_OSD)
#define IS_OSM(card)	((card)->info.type == QETH_CARD_TYPE_OSM)
#define IS_OSN(card)	((card)->info.type == QETH_CARD_TYPE_OSN)
#define IS_VM_NIC(card)	((card)->info.guestlan)

+70 −174
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@
#include "qeth_l2.h"

static int qeth_l2_set_offline(struct ccwgroup_device *);
static int qeth_l2_stop(struct net_device *);
static void qeth_bridgeport_query_support(struct qeth_card *card);
static void qeth_bridge_state_change(struct qeth_card *card,
					struct qeth_ipa_cmd *cmd);
@@ -98,8 +97,7 @@ static int qeth_l2_send_setmac(struct qeth_card *card, __u8 *mac)
	rc = qeth_l2_send_setdelmac(card, mac, IPA_CMD_SETVMAC);
	if (rc == 0) {
		dev_info(&card->gdev->dev,
			 "MAC address %pM successfully registered on device %s\n",
			 mac, card->dev->name);
			 "MAC address %pM successfully registered\n", mac);
	} else {
		switch (rc) {
		case -EEXIST:
@@ -263,75 +261,28 @@ static int qeth_l2_send_setdelvlan(struct qeth_card *card, __u16 i,
					    qeth_l2_send_setdelvlan_cb, NULL));
}

static void qeth_l2_process_vlans(struct qeth_card *card)
{
	struct qeth_vlan_vid *id;

	QETH_CARD_TEXT(card, 3, "L2prcvln");
	mutex_lock(&card->vid_list_mutex);
	list_for_each_entry(id, &card->vid_list, list) {
		qeth_l2_send_setdelvlan(card, id->vid, IPA_CMD_SETVLAN);
	}
	mutex_unlock(&card->vid_list_mutex);
}

static int qeth_l2_vlan_rx_add_vid(struct net_device *dev,
				   __be16 proto, u16 vid)
{
	struct qeth_card *card = dev->ml_priv;
	struct qeth_vlan_vid *id;
	int rc;

	QETH_CARD_TEXT_(card, 4, "aid:%d", vid);
	if (!vid)
		return 0;
	if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) {
		QETH_CARD_TEXT(card, 3, "aidREC");
		return 0;
	}
	id = kmalloc(sizeof(*id), GFP_KERNEL);
	if (id) {
		id->vid = vid;
		rc = qeth_l2_send_setdelvlan(card, vid, IPA_CMD_SETVLAN);
		if (rc) {
			kfree(id);
			return rc;
		}
		mutex_lock(&card->vid_list_mutex);
		list_add_tail(&id->list, &card->vid_list);
		mutex_unlock(&card->vid_list_mutex);
	} else {
		return -ENOMEM;
	}
	return 0;

	return qeth_l2_send_setdelvlan(card, vid, IPA_CMD_SETVLAN);
}

static int qeth_l2_vlan_rx_kill_vid(struct net_device *dev,
				    __be16 proto, u16 vid)
{
	struct qeth_vlan_vid *id, *tmpid = NULL;
	struct qeth_card *card = dev->ml_priv;
	int rc = 0;

	QETH_CARD_TEXT_(card, 4, "kid:%d", vid);
	if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) {
		QETH_CARD_TEXT(card, 3, "kidREC");
	if (!vid)
		return 0;
	}
	mutex_lock(&card->vid_list_mutex);
	list_for_each_entry(id, &card->vid_list, list) {
		if (id->vid == vid) {
			list_del(&id->list);
			tmpid = id;
			break;
		}
	}
	mutex_unlock(&card->vid_list_mutex);
	if (tmpid) {
		rc = qeth_l2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN);
		kfree(tmpid);
	}
	return rc;

	return qeth_l2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN);
}

static void qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
@@ -343,9 +294,8 @@ static void qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
	if (card->read.state == CH_STATE_UP &&
	    card->write.state == CH_STATE_UP &&
	    (card->state == CARD_STATE_UP)) {
		if (recovery_mode &&
		    card->info.type != QETH_CARD_TYPE_OSN) {
			qeth_l2_stop(card->dev);
		if (recovery_mode && !IS_OSN(card)) {
			qeth_stop(card->dev);
		} else {
			rtnl_lock();
			dev_close(card->dev);
@@ -460,6 +410,26 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card)
	return 0;
}

static void qeth_l2_register_dev_addr(struct qeth_card *card)
{
	if (!is_valid_ether_addr(card->dev->dev_addr))
		qeth_l2_request_initial_mac(card);

	if (!IS_OSN(card) && !qeth_l2_send_setmac(card, card->dev->dev_addr))
		card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED;
}

static int qeth_l2_validate_addr(struct net_device *dev)
{
	struct qeth_card *card = dev->ml_priv;

	if (IS_OSN(card) || (card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))
		return eth_validate_addr(dev);

	QETH_CARD_TEXT(card, 4, "nomacadr");
	return -EPERM;
}

static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
{
	struct sockaddr *addr = p;
@@ -479,39 +449,22 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
	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;
	}

	/* avoid racing against concurrent state change: */
	if (!mutex_trylock(&card->conf_mutex))
		return -EAGAIN;

	if (!qeth_card_hw_is_reachable(card)) {
		ether_addr_copy(dev->dev_addr, addr->sa_data);
		goto out_unlock;
	}

	/* 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))
		goto out_unlock;
		return 0;

	/* add the new address, switch over, drop the old */
	rc = qeth_l2_send_setmac(card, addr->sa_data);
	if (rc)
		goto out_unlock;
		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;

out_unlock:
	mutex_unlock(&card->conf_mutex);
	return rc;
	return 0;
}

static void qeth_promisc_to_bridge(struct qeth_card *card)
@@ -586,9 +539,6 @@ static void qeth_l2_set_rx_mode(struct net_device *dev)
		return;

	QETH_CARD_TEXT(card, 3, "setmulti");
	if (qeth_threads_running(card, QETH_RECOVER_THREAD) &&
	    (card->state != CARD_STATE_UP))
		return;

	spin_lock_bh(&card->mclock);

@@ -712,62 +662,6 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb,
	return NETDEV_TX_OK;
}

static int __qeth_l2_open(struct net_device *dev)
{
	struct qeth_card *card = dev->ml_priv;
	int rc = 0;

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

	if ((card->info.type != QETH_CARD_TYPE_OSN) &&
	     (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))) {
		QETH_CARD_TEXT(card, 4, "nomacadr");
		return -EPERM;
	}
	card->data.state = CH_STATE_UP;
	card->state = CARD_STATE_UP;
	netif_start_queue(dev);

	if (qdio_stop_irq(card->data.ccwdev, 0) >= 0) {
		napi_enable(&card->napi);
		local_bh_disable();
		napi_schedule(&card->napi);
		/* kick-start the NAPI softirq: */
		local_bh_enable();
	} else
		rc = -EIO;
	return rc;
}

static int qeth_l2_open(struct net_device *dev)
{
	struct qeth_card *card = dev->ml_priv;

	QETH_CARD_TEXT(card, 5, "qethope_");
	if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) {
		QETH_CARD_TEXT(card, 3, "openREC");
		return -ERESTARTSYS;
	}
	return __qeth_l2_open(dev);
}

static int qeth_l2_stop(struct net_device *dev)
{
	struct qeth_card *card = dev->ml_priv;

	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;
}

static const struct device_type qeth_l2_devtype = {
	.name = "qeth_layer2",
	.groups = qeth_l2_attr_groups,
@@ -783,7 +677,7 @@ static int qeth_l2_probe_device(struct ccwgroup_device *gdev)
		if (rc)
			return rc;
	}
	INIT_LIST_HEAD(&card->vid_list);

	hash_init(card->mac_htable);
	card->info.hwtrap = 0;
	qeth_l2_vnicc_set_defaults(card);
@@ -822,12 +716,12 @@ static const struct ethtool_ops qeth_l2_osn_ops = {
};

static const struct net_device_ops qeth_l2_netdev_ops = {
	.ndo_open		= qeth_l2_open,
	.ndo_stop		= qeth_l2_stop,
	.ndo_open		= qeth_open,
	.ndo_stop		= qeth_stop,
	.ndo_get_stats		= qeth_get_stats,
	.ndo_start_xmit		= qeth_l2_hard_start_xmit,
	.ndo_features_check	= qeth_features_check,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_validate_addr	= qeth_l2_validate_addr,
	.ndo_set_rx_mode	= qeth_l2_set_rx_mode,
	.ndo_do_ioctl		= qeth_do_ioctl,
	.ndo_set_mac_address    = qeth_l2_set_mac_address,
@@ -842,9 +736,6 @@ static int qeth_l2_setup_netdev(struct qeth_card *card, bool carrier_ok)
{
	int rc;

	if (qeth_netdev_is_registered(card->dev))
		return 0;

	card->dev->priv_flags |= IFF_UNICAST_FLT;
	card->dev->netdev_ops = &qeth_l2_netdev_ops;
	if (card->info.type == QETH_CARD_TYPE_OSN) {
@@ -855,10 +746,13 @@ static int qeth_l2_setup_netdev(struct qeth_card *card, bool carrier_ok)
		card->dev->needed_headroom = sizeof(struct qeth_hdr);
	}

	if (card->info.type == QETH_CARD_TYPE_OSM)
	if (IS_OSM(card)) {
		card->dev->features |= NETIF_F_VLAN_CHALLENGED;
	else
	} else {
		if (!IS_VM_NIC(card))
			card->dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
		card->dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
	}

	if (card->info.type == QETH_CARD_TYPE_OSD && !card->info.guestlan) {
		card->dev->features |= NETIF_F_SG;
@@ -892,8 +786,6 @@ static int qeth_l2_setup_netdev(struct qeth_card *card, bool carrier_ok)
				       PAGE_SIZE * (QDIO_MAX_ELEMENTS_PER_BUFFER - 1));
	}

	if (!is_valid_ether_addr(card->dev->dev_addr))
		qeth_l2_request_initial_mac(card);
	netif_napi_add(card->dev, &card->napi, qeth_poll, QETH_NAPI_WEIGHT);
	rc = register_netdev(card->dev);
	if (!rc && carrier_ok)
@@ -927,6 +819,7 @@ static void qeth_l2_trace_features(struct qeth_card *card)
static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
{
	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;
@@ -948,13 +841,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
		dev_info(&card->gdev->dev,
		"The device represents a Bridge Capable Port\n");

	rc = qeth_l2_setup_netdev(card, carrier_ok);
	if (rc)
		goto out_remove;

	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;
	qeth_l2_register_dev_addr(card);

	if (qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP)) {
		if (card->info.hwtrap &&
@@ -984,11 +871,6 @@ 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_process_vlans(card);

	netif_tx_disable(card->dev);

	rc = qeth_init_qdio_queues(card);
	if (rc) {
		QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc);
@@ -999,18 +881,32 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)

	qeth_set_allowed_threads(card, 0xffffffff, 0);

	qeth_enable_hw_features(card->dev);
	if (recover_flag == CARD_STATE_RECOVER) {
		if (recovery_mode &&
		    card->info.type != QETH_CARD_TYPE_OSN) {
			__qeth_l2_open(card->dev);
			qeth_l2_set_rx_mode(card->dev);
	if (!qeth_netdev_is_registered(dev)) {
		rc = qeth_l2_setup_netdev(card, carrier_ok);
		if (rc)
			goto out_remove;
	} else {
		rtnl_lock();
			dev_open(card->dev, NULL);
			rtnl_unlock();
		if (carrier_ok)
			netif_carrier_on(dev);
		else
			netif_carrier_off(dev);

		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 {
				dev_open(dev, NULL);
			}
		}
		rtnl_unlock();
	}
	/* let user_space know that device is online */
	kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
	mutex_unlock(&card->conf_mutex);
@@ -1049,7 +945,11 @@ static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev,
	QETH_DBF_TEXT(SETUP, 3, "setoffl");
	QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *));

	rtnl_lock();
	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);
@@ -1090,7 +990,6 @@ static int qeth_l2_recover(void *ptr)
	QETH_CARD_TEXT(card, 2, "recover2");
	dev_warn(&card->gdev->dev,
		"A recovery process has been started for the device\n");
	qeth_set_recovery_task(card);
	__qeth_l2_set_offline(card->gdev, 1);
	rc = __qeth_l2_set_online(card->gdev, 1);
	if (!rc)
@@ -1101,7 +1000,6 @@ static int qeth_l2_recover(void *ptr)
		dev_warn(&card->gdev->dev, "The qeth device driver "
				"failed to recover an error on the device\n");
	}
	qeth_clear_recovery_task(card);
	qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
	qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
	return 0;
@@ -1122,7 +1020,6 @@ static int qeth_l2_pm_suspend(struct ccwgroup_device *gdev)
{
	struct qeth_card *card = dev_get_drvdata(&gdev->dev);

	netif_device_detach(card->dev);
	qeth_set_allowed_threads(card, 0, 1);
	wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
	if (gdev->state == CCWGROUP_OFFLINE)
@@ -1152,7 +1049,6 @@ static int qeth_l2_pm_resume(struct ccwgroup_device *gdev)
		rc = __qeth_l2_set_online(card->gdev, 0);

	qeth_set_allowed_threads(card, 0xffffffff, 0);
	netif_device_attach(card->dev);
	if (rc)
		dev_warn(&card->gdev->dev, "The qeth device driver "
			"failed to recover an error on the device\n");
+31 −82

File changed.

Preview size limit exceeded, changes collapsed.