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

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
...@@ -741,11 +741,6 @@ struct qeth_discipline { ...@@ -741,11 +741,6 @@ struct qeth_discipline {
struct qeth_ipa_cmd *cmd); struct qeth_ipa_cmd *cmd);
}; };
struct qeth_vlan_vid {
struct list_head list;
unsigned short vid;
};
enum qeth_addr_disposition { enum qeth_addr_disposition {
QETH_DISP_ADDR_DELETE = 0, QETH_DISP_ADDR_DELETE = 0,
QETH_DISP_ADDR_DO_NOTHING = 1, QETH_DISP_ADDR_DO_NOTHING = 1,
...@@ -792,8 +787,6 @@ struct qeth_card { ...@@ -792,8 +787,6 @@ struct qeth_card {
wait_queue_head_t wait_q; wait_queue_head_t wait_q;
spinlock_t mclock; spinlock_t mclock;
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; 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(mac_htable, 4);
DECLARE_HASHTABLE(ip_htable, 4); DECLARE_HASHTABLE(ip_htable, 4);
DECLARE_HASHTABLE(ip_mc_htable, 4); DECLARE_HASHTABLE(ip_mc_htable, 4);
...@@ -802,7 +795,6 @@ struct qeth_card { ...@@ -802,7 +795,6 @@ struct qeth_card {
unsigned long thread_start_mask; unsigned long thread_start_mask;
unsigned long thread_allowed_mask; unsigned long thread_allowed_mask;
unsigned long thread_running_mask; unsigned long thread_running_mask;
struct task_struct *recovery_task;
spinlock_t ip_lock; spinlock_t ip_lock;
struct qeth_ipato ipato; struct qeth_ipato ipato;
struct list_head cmd_waiter_list; struct list_head cmd_waiter_list;
...@@ -976,11 +968,8 @@ extern struct qeth_dbf_info qeth_dbf[QETH_DBF_INFOS]; ...@@ -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 net_device *qeth_clone_netdev(struct net_device *orig);
struct qeth_card *qeth_get_card_by_busid(char *bus_id); 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); void qeth_set_allowed_threads(struct qeth_card *, unsigned long , int);
int qeth_threads_running(struct qeth_card *, unsigned long); 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); 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_start_bit(struct qeth_card *, unsigned long);
void qeth_clear_thread_running_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); ...@@ -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, netdev_features_t qeth_features_check(struct sk_buff *skb,
struct net_device *dev, struct net_device *dev,
netdev_features_t features); 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_vm_request_mac(struct qeth_card *card);
int qeth_xmit(struct qeth_card *card, struct sk_buff *skb, int qeth_xmit(struct qeth_card *card, struct sk_buff *skb,
struct qeth_qdio_out_q *queue, int ipv, int cast_type, struct qeth_qdio_out_q *queue, int ipv, int cast_type,
......
...@@ -193,23 +193,6 @@ const char *qeth_get_cardname_short(struct qeth_card *card) ...@@ -193,23 +193,6 @@ const char *qeth_get_cardname_short(struct qeth_card *card)
return "n/a"; 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, void qeth_set_allowed_threads(struct qeth_card *card, unsigned long threads,
int clear_start_mask) int clear_start_mask)
{ {
...@@ -236,15 +219,6 @@ int qeth_threads_running(struct qeth_card *card, unsigned long threads) ...@@ -236,15 +219,6 @@ int qeth_threads_running(struct qeth_card *card, unsigned long threads)
} }
EXPORT_SYMBOL_GPL(qeth_threads_running); 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) void qeth_clear_working_pool_list(struct qeth_card *card)
{ {
struct qeth_buffer_pool_entry *pool_entry, *tmp; struct qeth_buffer_pool_entry *pool_entry, *tmp;
...@@ -1430,7 +1404,6 @@ static void qeth_setup_card(struct qeth_card *card) ...@@ -1430,7 +1404,6 @@ static void qeth_setup_card(struct qeth_card *card)
spin_lock_init(&card->thread_mask_lock); spin_lock_init(&card->thread_mask_lock);
mutex_init(&card->conf_mutex); mutex_init(&card->conf_mutex);
mutex_init(&card->discipline_mutex); mutex_init(&card->discipline_mutex);
mutex_init(&card->vid_list_mutex);
INIT_WORK(&card->kernel_thread_starter, qeth_start_kernel_thread); INIT_WORK(&card->kernel_thread_starter, qeth_start_kernel_thread);
INIT_LIST_HEAD(&card->cmd_waiter_list); INIT_LIST_HEAD(&card->cmd_waiter_list);
init_waitqueue_head(&card->wait_q); init_waitqueue_head(&card->wait_q);
...@@ -3558,8 +3531,6 @@ static void qeth_qdio_cq_handler(struct qeth_card *card, unsigned int qdio_err, ...@@ -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 card->qdio.c_q->next_buf_to_init = (card->qdio.c_q->next_buf_to_init
+ count) % QDIO_MAX_BUFFERS_PER_Q; + count) % QDIO_MAX_BUFFERS_PER_Q;
netif_wake_queue(card->dev);
if (card->options.performance_stats) { if (card->options.performance_stats) {
int delta_t = qeth_get_micros(); int delta_t = qeth_get_micros();
delta_t -= card->perf_stats.cq_start_time; delta_t -= card->perf_stats.cq_start_time;
...@@ -3928,7 +3899,6 @@ static int qeth_fill_buffer(struct qeth_qdio_out_q *queue, ...@@ -3928,7 +3899,6 @@ static int qeth_fill_buffer(struct qeth_qdio_out_q *queue,
{ {
struct qdio_buffer *buffer = buf->buffer; struct qdio_buffer *buffer = buf->buffer;
bool is_first_elem = true; bool is_first_elem = true;
int flush_cnt = 0;
__skb_queue_tail(&buf->skb_list, skb); __skb_queue_tail(&buf->skb_list, skb);
...@@ -3949,24 +3919,22 @@ static int qeth_fill_buffer(struct qeth_qdio_out_q *queue, ...@@ -3949,24 +3919,22 @@ static int qeth_fill_buffer(struct qeth_qdio_out_q *queue,
if (!queue->do_pack) { if (!queue->do_pack) {
QETH_CARD_TEXT(queue->card, 6, "fillbfnp"); 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 { } else {
QETH_CARD_TEXT(queue->card, 6, "fillbfpa"); QETH_CARD_TEXT(queue->card, 6, "fillbfpa");
if (queue->card->options.performance_stats) if (queue->card->options.performance_stats)
queue->card->perf_stats.skbs_sent_pack++; queue->card->perf_stats.skbs_sent_pack++;
if (buf->next_element_to_fill >=
QETH_MAX_BUFFER_ELEMENTS(queue->card)) { /* If the buffer still has free elements, keep using it. */
/* if (buf->next_element_to_fill <
* packed buffer if full -> set state PRIMED QETH_MAX_BUFFER_ELEMENTS(queue->card))
* -> will be flushed return 0;
*/
atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
flush_cnt = 1;
}
} }
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, 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, ...@@ -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) if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY)
return -EBUSY; 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_fill_buffer(queue, buffer, skb, hdr, offset, hd_len);
qeth_flush_buffers(queue, index, 1); qeth_flush_buffers(queue, index, 1);
return 0; return 0;
...@@ -4040,10 +4007,9 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, ...@@ -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) % flush_count += qeth_fill_buffer(queue, buffer, skb, hdr, offset,
QDIO_MAX_BUFFERS_PER_Q; hd_len);
flush_count += tmp;
if (flush_count) if (flush_count)
qeth_flush_buffers(queue, start_index, flush_count); qeth_flush_buffers(queue, start_index, flush_count);
else if (!atomic_read(&queue->set_pci_flags_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) ...@@ -5154,13 +5120,6 @@ int qeth_core_hardsetup_card(struct qeth_card *card, bool *carrier_ok)
*carrier_ok = true; *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.ipa4.supported_funcs = 0;
card->options.ipa6.supported_funcs = 0; card->options.ipa6.supported_funcs = 0;
card->options.adp.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) ...@@ -5937,9 +5896,6 @@ int qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
if (!card) if (!card)
return -ENODEV; return -ENODEV;
if (!qeth_card_hw_is_reachable(card))
return -ENODEV;
if (card->info.type == QETH_CARD_TYPE_OSN) if (card->info.type == QETH_CARD_TYPE_OSN)
return -EPERM; return -EPERM;
...@@ -6250,8 +6206,6 @@ int qeth_core_ethtool_get_link_ksettings(struct net_device *netdev, ...@@ -6250,8 +6206,6 @@ int qeth_core_ethtool_get_link_ksettings(struct net_device *netdev,
/* Check if we can obtain more accurate information. */ /* Check if we can obtain more accurate information. */
/* If QUERY_CARD_INFO command is not supported or fails, */ /* If QUERY_CARD_INFO command is not supported or fails, */
/* just return the heuristics that was filled above. */ /* 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); rc = qeth_query_card_info(card, &carrier_info);
if (rc == -EOPNOTSUPP) /* for old hardware, return heuristic */ if (rc == -EOPNOTSUPP) /* for old hardware, return heuristic */
return 0; return 0;
...@@ -6534,8 +6488,6 @@ static int qeth_set_ipa_rx_csum(struct qeth_card *card, bool on) ...@@ -6534,8 +6488,6 @@ static int qeth_set_ipa_rx_csum(struct qeth_card *card, bool on)
return (rc_ipv6) ? rc_ipv6 : rc_ipv4; 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 * qeth_enable_hw_features() - (Re-)Enable HW functions for device features
* @dev: a net_device * @dev: a net_device
...@@ -6545,17 +6497,20 @@ void qeth_enable_hw_features(struct net_device *dev) ...@@ -6545,17 +6497,20 @@ void qeth_enable_hw_features(struct net_device *dev)
struct qeth_card *card = dev->ml_priv; struct qeth_card *card = dev->ml_priv;
netdev_features_t features; netdev_features_t features;
rtnl_lock();
features = dev->features; 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. * 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); netdev_update_features(dev);
if (features != dev->features) if (features != dev->features)
dev_warn(&card->gdev->dev, dev_warn(&card->gdev->dev,
"Device recovery failed to restore all offload features\n"); "Device recovery failed to restore all offload features\n");
rtnl_unlock();
} }
EXPORT_SYMBOL_GPL(qeth_enable_hw_features); EXPORT_SYMBOL_GPL(qeth_enable_hw_features);
...@@ -6624,10 +6579,7 @@ netdev_features_t qeth_fix_features(struct net_device *dev, ...@@ -6624,10 +6579,7 @@ netdev_features_t qeth_fix_features(struct net_device *dev,
features &= ~NETIF_F_TSO; features &= ~NETIF_F_TSO;
if (!qeth_is_supported6(card, IPA_OUTBOUND_TSO)) if (!qeth_is_supported6(card, IPA_OUTBOUND_TSO))
features &= ~NETIF_F_TSO6; 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)); QETH_DBF_HEX(SETUP, 2, &features, sizeof(features));
return features; return features;
} }
...@@ -6659,6 +6611,46 @@ netdev_features_t qeth_features_check(struct sk_buff *skb, ...@@ -6659,6 +6611,46 @@ netdev_features_t qeth_features_check(struct sk_buff *skb,
} }
EXPORT_SYMBOL_GPL(qeth_features_check); 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) static int __init qeth_core_init(void)
{ {
int rc; int rc;
......
...@@ -81,6 +81,7 @@ enum qeth_card_types { ...@@ -81,6 +81,7 @@ enum qeth_card_types {
#define IS_IQD(card) ((card)->info.type == QETH_CARD_TYPE_IQD) #define IS_IQD(card) ((card)->info.type == QETH_CARD_TYPE_IQD)
#define IS_OSD(card) ((card)->info.type == QETH_CARD_TYPE_OSD) #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_OSN(card) ((card)->info.type == QETH_CARD_TYPE_OSN)
#define IS_VM_NIC(card) ((card)->info.guestlan) #define IS_VM_NIC(card) ((card)->info.guestlan)
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include "qeth_l2.h" #include "qeth_l2.h"
static int qeth_l2_set_offline(struct ccwgroup_device *); 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_bridgeport_query_support(struct qeth_card *card);
static void qeth_bridge_state_change(struct qeth_card *card, static void qeth_bridge_state_change(struct qeth_card *card,
struct qeth_ipa_cmd *cmd); struct qeth_ipa_cmd *cmd);
...@@ -98,8 +97,7 @@ static int qeth_l2_send_setmac(struct qeth_card *card, __u8 *mac) ...@@ -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); rc = qeth_l2_send_setdelmac(card, mac, IPA_CMD_SETVMAC);
if (rc == 0) { if (rc == 0) {
dev_info(&card->gdev->dev, dev_info(&card->gdev->dev,
"MAC address %pM successfully registered on device %s\n", "MAC address %pM successfully registered\n", mac);
mac, card->dev->name);
} else { } else {
switch (rc) { switch (rc) {
case -EEXIST: case -EEXIST:
...@@ -263,75 +261,28 @@ static int qeth_l2_send_setdelvlan(struct qeth_card *card, __u16 i, ...@@ -263,75 +261,28 @@ static int qeth_l2_send_setdelvlan(struct qeth_card *card, __u16 i,
qeth_l2_send_setdelvlan_cb, NULL)); 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, static int qeth_l2_vlan_rx_add_vid(struct net_device *dev,
__be16 proto, u16 vid) __be16 proto, u16 vid)
{ {
struct qeth_card *card = dev->ml_priv; struct qeth_card *card = dev->ml_priv;
struct qeth_vlan_vid *id;
int rc;
QETH_CARD_TEXT_(card, 4, "aid:%d", vid); QETH_CARD_TEXT_(card, 4, "aid:%d", vid);
if (!vid) if (!vid)
return 0; return 0;
if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) {
QETH_CARD_TEXT(card, 3, "aidREC"); return qeth_l2_send_setdelvlan(card, vid, IPA_CMD_SETVLAN);
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;
} }
static int qeth_l2_vlan_rx_kill_vid(struct net_device *dev, static int qeth_l2_vlan_rx_kill_vid(struct net_device *dev,
__be16 proto, u16 vid) __be16 proto, u16 vid)
{ {
struct qeth_vlan_vid *id, *tmpid = NULL;
struct qeth_card *card = dev->ml_priv; struct qeth_card *card = dev->ml_priv;
int rc = 0;
QETH_CARD_TEXT_(card, 4, "kid:%d", vid); QETH_CARD_TEXT_(card, 4, "kid:%d", vid);
if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) { if (!vid)
QETH_CARD_TEXT(card, 3, "kidREC");
return 0; return 0;
}
mutex_lock(&card->vid_list_mutex); return qeth_l2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN);
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;
} }
static void qeth_l2_stop_card(struct qeth_card *card, int recovery_mode) 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) ...@@ -343,9 +294,8 @@ static void qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
if (card->read.state == CH_STATE_UP && if (card->read.state == CH_STATE_UP &&
card->write.state == CH_STATE_UP && card->write.state == CH_STATE_UP &&
(card->state == CARD_STATE_UP)) { (card->state == CARD_STATE_UP)) {
if (recovery_mode && if (recovery_mode && !IS_OSN(card)) {
card->info.type != QETH_CARD_TYPE_OSN) { qeth_stop(card->dev);
qeth_l2_stop(card->dev);
} else { } else {
rtnl_lock(); rtnl_lock();
dev_close(card->dev); dev_close(card->dev);
...@@ -460,6 +410,26 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card) ...@@ -460,6 +410,26 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card)
return 0; 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) static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
{ {
struct sockaddr *addr = p; struct sockaddr *addr = p;
...@@ -479,39 +449,22 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *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)) if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL; 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 */ /* don't register the same address twice */
if (ether_addr_equal_64bits(dev->dev_addr, addr->sa_data) && if (ether_addr_equal_64bits(dev->dev_addr, addr->sa_data) &&
(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED)) (card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))
goto out_unlock; return 0;
/* add the new address, switch over, drop the old */ /* add the new address, switch over, drop the old */
rc = qeth_l2_send_setmac(card, addr->sa_data); rc = qeth_l2_send_setmac(card, addr->sa_data);
if (rc) if (rc)
goto out_unlock; return rc;
ether_addr_copy(old_addr, dev->dev_addr); ether_addr_copy(old_addr, dev->dev_addr);
ether_addr_copy(dev->dev_addr, addr->sa_data); ether_addr_copy(dev->dev_addr, addr->sa_data);
if (card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED) if (card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED)
qeth_l2_remove_mac(card, old_addr); qeth_l2_remove_mac(card, old_addr);
card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED; card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED;
return 0;
out_unlock:
mutex_unlock(&card->conf_mutex);
return rc;
} }
static void qeth_promisc_to_bridge(struct qeth_card *card) 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) ...@@ -586,9 +539,6 @@ static void qeth_l2_set_rx_mode(struct net_device *dev)
return; return;
QETH_CARD_TEXT(card, 3, "setmulti"); 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); spin_lock_bh(&card->mclock);
...@@ -712,62 +662,6 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb, ...@@ -712,62 +662,6 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb,
return NETDEV_TX_OK; 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 = { static const struct device_type qeth_l2_devtype = {
.name = "qeth_layer2", .name = "qeth_layer2",
.groups = qeth_l2_attr_groups, .groups = qeth_l2_attr_groups,
...@@ -783,7 +677,7 @@ static int qeth_l2_probe_device(struct ccwgroup_device *gdev) ...@@ -783,7 +677,7 @@ static int qeth_l2_probe_device(struct ccwgroup_device *gdev)
if (rc) if (rc)
return rc; return rc;
} }
INIT_LIST_HEAD(&card->vid_list);
hash_init(card->mac_htable); hash_init(card->mac_htable);
card->info.hwtrap = 0; card->info.hwtrap = 0;
qeth_l2_vnicc_set_defaults(card); qeth_l2_vnicc_set_defaults(card);
...@@ -822,12 +716,12 @@ static const struct ethtool_ops qeth_l2_osn_ops = { ...@@ -822,12 +716,12 @@ static const struct ethtool_ops qeth_l2_osn_ops = {
}; };
static const struct net_device_ops qeth_l2_netdev_ops = { static const struct net_device_ops qeth_l2_netdev_ops = {
.ndo_open = qeth_l2_open, .ndo_open = qeth_open,
.ndo_stop = qeth_l2_stop, .ndo_stop = qeth_stop,
.ndo_get_stats = qeth_get_stats, .ndo_get_stats = qeth_get_stats,
.ndo_start_xmit = qeth_l2_hard_start_xmit, .ndo_start_xmit = qeth_l2_hard_start_xmit,
.ndo_features_check = qeth_features_check, .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_set_rx_mode = qeth_l2_set_rx_mode,
.ndo_do_ioctl = qeth_do_ioctl, .ndo_do_ioctl = qeth_do_ioctl,
.ndo_set_mac_address = qeth_l2_set_mac_address, .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) ...@@ -842,9 +736,6 @@ static int qeth_l2_setup_netdev(struct qeth_card *card, bool carrier_ok)
{ {
int rc; int rc;
if (qeth_netdev_is_registered(card->dev))
return 0;
card->dev->priv_flags |= IFF_UNICAST_FLT; card->dev->priv_flags |= IFF_UNICAST_FLT;
card->dev->netdev_ops = &qeth_l2_netdev_ops; card->dev->netdev_ops = &qeth_l2_netdev_ops;
if (card->info.type == QETH_CARD_TYPE_OSN) { 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) ...@@ -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); 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; 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; card->dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
}
if (card->info.type == QETH_CARD_TYPE_OSD && !card->info.guestlan) { if (card->info.type == QETH_CARD_TYPE_OSD && !card->info.guestlan) {
card->dev->features |= NETIF_F_SG; card->dev->features |= NETIF_F_SG;
...@@ -892,8 +786,6 @@ static int qeth_l2_setup_netdev(struct qeth_card *card, bool carrier_ok) ...@@ -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)); 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); netif_napi_add(card->dev, &card->napi, qeth_poll, QETH_NAPI_WEIGHT);
rc = register_netdev(card->dev); rc = register_netdev(card->dev);
if (!rc && carrier_ok) if (!rc && carrier_ok)
...@@ -927,6 +819,7 @@ static void qeth_l2_trace_features(struct qeth_card *card) ...@@ -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) static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
{ {
struct qeth_card *card = dev_get_drvdata(&gdev->dev); struct qeth_card *card = dev_get_drvdata(&gdev->dev);
struct net_device *dev = card->dev;
int rc = 0; int rc = 0;
enum qeth_card_states recover_flag; enum qeth_card_states recover_flag;
bool carrier_ok; bool carrier_ok;
...@@ -948,13 +841,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) ...@@ -948,13 +841,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
dev_info(&card->gdev->dev, dev_info(&card->gdev->dev,
"The device represents a Bridge Capable Port\n"); "The device represents a Bridge Capable Port\n");
rc = qeth_l2_setup_netdev(card, carrier_ok); qeth_l2_register_dev_addr(card);
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;
if (qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP)) { if (qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP)) {
if (card->info.hwtrap && if (card->info.hwtrap &&
...@@ -984,11 +871,6 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) ...@@ -984,11 +871,6 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
goto out_remove; 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); rc = qeth_init_qdio_queues(card);
if (rc) { if (rc) {
QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc); QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc);
...@@ -999,17 +881,31 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) ...@@ -999,17 +881,31 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
qeth_set_allowed_threads(card, 0xffffffff, 0); qeth_set_allowed_threads(card, 0xffffffff, 0);
qeth_enable_hw_features(card->dev); if (!qeth_netdev_is_registered(dev)) {
if (recover_flag == CARD_STATE_RECOVER) { rc = qeth_l2_setup_netdev(card, carrier_ok);
if (recovery_mode && if (rc)
card->info.type != QETH_CARD_TYPE_OSN) { goto out_remove;
__qeth_l2_open(card->dev); } else {
qeth_l2_set_rx_mode(card->dev); rtnl_lock();
} else { if (carrier_ok)
rtnl_lock(); netif_carrier_on(dev);
dev_open(card->dev, NULL); else
rtnl_unlock(); 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 */ /* let user_space know that device is online */
kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE); kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
...@@ -1049,7 +945,11 @@ static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev, ...@@ -1049,7 +945,11 @@ static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev,
QETH_DBF_TEXT(SETUP, 3, "setoffl"); QETH_DBF_TEXT(SETUP, 3, "setoffl");
QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *)); QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *));
rtnl_lock();
netif_device_detach(card->dev);
netif_carrier_off(card->dev); netif_carrier_off(card->dev);
rtnl_unlock();
recover_flag = card->state; recover_flag = card->state;
if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) { if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) {
qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM);
...@@ -1090,7 +990,6 @@ static int qeth_l2_recover(void *ptr) ...@@ -1090,7 +990,6 @@ static int qeth_l2_recover(void *ptr)
QETH_CARD_TEXT(card, 2, "recover2"); QETH_CARD_TEXT(card, 2, "recover2");
dev_warn(&card->gdev->dev, dev_warn(&card->gdev->dev,
"A recovery process has been started for the device\n"); "A recovery process has been started for the device\n");
qeth_set_recovery_task(card);
__qeth_l2_set_offline(card->gdev, 1); __qeth_l2_set_offline(card->gdev, 1);
rc = __qeth_l2_set_online(card->gdev, 1); rc = __qeth_l2_set_online(card->gdev, 1);
if (!rc) if (!rc)
...@@ -1101,7 +1000,6 @@ static int qeth_l2_recover(void *ptr) ...@@ -1101,7 +1000,6 @@ static int qeth_l2_recover(void *ptr)
dev_warn(&card->gdev->dev, "The qeth device driver " dev_warn(&card->gdev->dev, "The qeth device driver "
"failed to recover an error on the device\n"); "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_start_bit(card, QETH_RECOVER_THREAD);
qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD); qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
return 0; return 0;
...@@ -1122,7 +1020,6 @@ static int qeth_l2_pm_suspend(struct ccwgroup_device *gdev) ...@@ -1122,7 +1020,6 @@ static int qeth_l2_pm_suspend(struct ccwgroup_device *gdev)
{ {
struct qeth_card *card = dev_get_drvdata(&gdev->dev); struct qeth_card *card = dev_get_drvdata(&gdev->dev);
netif_device_detach(card->dev);
qeth_set_allowed_threads(card, 0, 1); qeth_set_allowed_threads(card, 0, 1);
wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0); wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
if (gdev->state == CCWGROUP_OFFLINE) if (gdev->state == CCWGROUP_OFFLINE)
...@@ -1152,7 +1049,6 @@ static int qeth_l2_pm_resume(struct ccwgroup_device *gdev) ...@@ -1152,7 +1049,6 @@ static int qeth_l2_pm_resume(struct ccwgroup_device *gdev)
rc = __qeth_l2_set_online(card->gdev, 0); rc = __qeth_l2_set_online(card->gdev, 0);
qeth_set_allowed_threads(card, 0xffffffff, 0); qeth_set_allowed_threads(card, 0xffffffff, 0);
netif_device_attach(card->dev);
if (rc) if (rc)
dev_warn(&card->gdev->dev, "The qeth device driver " dev_warn(&card->gdev->dev, "The qeth device driver "
"failed to recover an error on the device\n"); "failed to recover an error on the device\n");
......
...@@ -40,7 +40,6 @@ ...@@ -40,7 +40,6 @@
static int qeth_l3_set_offline(struct ccwgroup_device *); static int qeth_l3_set_offline(struct ccwgroup_device *);
static int qeth_l3_stop(struct net_device *);
static void qeth_l3_set_rx_mode(struct net_device *dev); static void qeth_l3_set_rx_mode(struct net_device *dev);
static int qeth_l3_register_addr_entry(struct qeth_card *, static int qeth_l3_register_addr_entry(struct qeth_card *,
struct qeth_ipaddr *); struct qeth_ipaddr *);
...@@ -1281,10 +1280,6 @@ static int qeth_l3_vlan_rx_kill_vid(struct net_device *dev, ...@@ -1281,10 +1280,6 @@ static int qeth_l3_vlan_rx_kill_vid(struct net_device *dev,
QETH_CARD_TEXT_(card, 4, "kid:%d", vid); QETH_CARD_TEXT_(card, 4, "kid:%d", vid);
if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) {
QETH_CARD_TEXT(card, 3, "kidREC");
return 0;
}
clear_bit(vid, card->active_vlans); clear_bit(vid, card->active_vlans);
qeth_l3_set_rx_mode(dev); qeth_l3_set_rx_mode(dev);
return 0; return 0;
...@@ -1410,7 +1405,7 @@ static void qeth_l3_stop_card(struct qeth_card *card, int recovery_mode) ...@@ -1410,7 +1405,7 @@ static void qeth_l3_stop_card(struct qeth_card *card, int recovery_mode)
card->write.state == CH_STATE_UP && card->write.state == CH_STATE_UP &&
(card->state == CARD_STATE_UP)) { (card->state == CARD_STATE_UP)) {
if (recovery_mode) if (recovery_mode)
qeth_l3_stop(card->dev); qeth_stop(card->dev);
else { else {
rtnl_lock(); rtnl_lock();
dev_close(card->dev); dev_close(card->dev);
...@@ -1473,9 +1468,7 @@ static void qeth_l3_set_rx_mode(struct net_device *dev) ...@@ -1473,9 +1468,7 @@ static void qeth_l3_set_rx_mode(struct net_device *dev)
int i, rc; int i, rc;
QETH_CARD_TEXT(card, 3, "setmulti"); QETH_CARD_TEXT(card, 3, "setmulti");
if (qeth_threads_running(card, QETH_RECOVER_THREAD) &&
(card->state != CARD_STATE_UP))
return;
if (!card->options.sniffer) { if (!card->options.sniffer) {
spin_lock_bh(&card->mclock); spin_lock_bh(&card->mclock);
...@@ -2100,56 +2093,6 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb, ...@@ -2100,56 +2093,6 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
static int __qeth_l3_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;
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_l3_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_l3_open(dev);
}
static int qeth_l3_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 ethtool_ops qeth_l3_ethtool_ops = { static const struct ethtool_ops qeth_l3_ethtool_ops = {
.get_link = ethtool_op_get_link, .get_link = ethtool_op_get_link,
.get_strings = qeth_core_get_strings, .get_strings = qeth_core_get_strings,
...@@ -2193,8 +2136,8 @@ static netdev_features_t qeth_l3_osa_features_check(struct sk_buff *skb, ...@@ -2193,8 +2136,8 @@ static netdev_features_t qeth_l3_osa_features_check(struct sk_buff *skb,
} }
static const struct net_device_ops qeth_l3_netdev_ops = { static const struct net_device_ops qeth_l3_netdev_ops = {
.ndo_open = qeth_l3_open, .ndo_open = qeth_open,
.ndo_stop = qeth_l3_stop, .ndo_stop = qeth_stop,
.ndo_get_stats = qeth_get_stats, .ndo_get_stats = qeth_get_stats,
.ndo_start_xmit = qeth_l3_hard_start_xmit, .ndo_start_xmit = qeth_l3_hard_start_xmit,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
...@@ -2208,8 +2151,8 @@ static const struct net_device_ops qeth_l3_netdev_ops = { ...@@ -2208,8 +2151,8 @@ static const struct net_device_ops qeth_l3_netdev_ops = {
}; };
static const struct net_device_ops qeth_l3_osa_netdev_ops = { static const struct net_device_ops qeth_l3_osa_netdev_ops = {
.ndo_open = qeth_l3_open, .ndo_open = qeth_open,
.ndo_stop = qeth_l3_stop, .ndo_stop = qeth_stop,
.ndo_get_stats = qeth_get_stats, .ndo_get_stats = qeth_get_stats,
.ndo_start_xmit = qeth_l3_hard_start_xmit, .ndo_start_xmit = qeth_l3_hard_start_xmit,
.ndo_features_check = qeth_l3_osa_features_check, .ndo_features_check = qeth_l3_osa_features_check,
...@@ -2229,9 +2172,6 @@ static int qeth_l3_setup_netdev(struct qeth_card *card, bool carrier_ok) ...@@ -2229,9 +2172,6 @@ static int qeth_l3_setup_netdev(struct qeth_card *card, bool carrier_ok)
unsigned int headroom; unsigned int headroom;
int rc; int rc;
if (qeth_netdev_is_registered(card->dev))
return 0;
if (card->info.type == QETH_CARD_TYPE_OSD || if (card->info.type == QETH_CARD_TYPE_OSD ||
card->info.type == QETH_CARD_TYPE_OSX) { card->info.type == QETH_CARD_TYPE_OSX) {
if ((card->info.link_type == QETH_LINK_TYPE_LANE_TR) || if ((card->info.link_type == QETH_LINK_TYPE_LANE_TR) ||
...@@ -2347,6 +2287,7 @@ static void qeth_l3_remove_device(struct ccwgroup_device *cgdev) ...@@ -2347,6 +2287,7 @@ static void qeth_l3_remove_device(struct ccwgroup_device *cgdev)
static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
{ {
struct qeth_card *card = dev_get_drvdata(&gdev->dev); struct qeth_card *card = dev_get_drvdata(&gdev->dev);
struct net_device *dev = card->dev;
int rc = 0; int rc = 0;
enum qeth_card_states recover_flag; enum qeth_card_states recover_flag;
bool carrier_ok; bool carrier_ok;
...@@ -2364,10 +2305,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) ...@@ -2364,10 +2305,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
goto out_remove; goto out_remove;
} }
rc = qeth_l3_setup_netdev(card, carrier_ok);
if (rc)
goto out_remove;
if (qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP)) { if (qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP)) {
if (card->info.hwtrap && if (card->info.hwtrap &&
qeth_hw_trap(card, QETH_DIAGS_TRAP_ARM)) qeth_hw_trap(card, QETH_DIAGS_TRAP_ARM))
...@@ -2397,7 +2334,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) ...@@ -2397,7 +2334,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
if (rc) if (rc)
QETH_DBF_TEXT_(SETUP, 2, "5err%04x", rc); QETH_DBF_TEXT_(SETUP, 2, "5err%04x", rc);
} }
netif_tx_disable(card->dev);
rc = qeth_init_qdio_queues(card); rc = qeth_init_qdio_queues(card);
if (rc) { if (rc) {
...@@ -2410,14 +2346,27 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) ...@@ -2410,14 +2346,27 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
qeth_set_allowed_threads(card, 0xffffffff, 0); qeth_set_allowed_threads(card, 0xffffffff, 0);
qeth_l3_recover_ip(card); qeth_l3_recover_ip(card);
qeth_enable_hw_features(card->dev); if (!qeth_netdev_is_registered(dev)) {
if (recover_flag == CARD_STATE_RECOVER) { rc = qeth_l3_setup_netdev(card, carrier_ok);
if (rc)
goto out_remove;
} else {
rtnl_lock(); rtnl_lock();
if (recovery_mode) { if (carrier_ok)
__qeth_l3_open(card->dev); netif_carrier_on(dev);
qeth_l3_set_rx_mode(card->dev); else
} else { netif_carrier_off(dev);
dev_open(card->dev, NULL);
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 {
dev_open(dev, NULL);
}
} }
rtnl_unlock(); rtnl_unlock();
} }
...@@ -2459,7 +2408,11 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev, ...@@ -2459,7 +2408,11 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev,
QETH_DBF_TEXT(SETUP, 3, "setoffl"); QETH_DBF_TEXT(SETUP, 3, "setoffl");
QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *)); QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *));
rtnl_lock();
netif_device_detach(card->dev);
netif_carrier_off(card->dev); netif_carrier_off(card->dev);
rtnl_unlock();
recover_flag = card->state; recover_flag = card->state;
if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) { if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) {
qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM);
...@@ -2506,7 +2459,6 @@ static int qeth_l3_recover(void *ptr) ...@@ -2506,7 +2459,6 @@ static int qeth_l3_recover(void *ptr)
QETH_CARD_TEXT(card, 2, "recover2"); QETH_CARD_TEXT(card, 2, "recover2");
dev_warn(&card->gdev->dev, dev_warn(&card->gdev->dev,
"A recovery process has been started for the device\n"); "A recovery process has been started for the device\n");
qeth_set_recovery_task(card);
__qeth_l3_set_offline(card->gdev, 1); __qeth_l3_set_offline(card->gdev, 1);
rc = __qeth_l3_set_online(card->gdev, 1); rc = __qeth_l3_set_online(card->gdev, 1);
if (!rc) if (!rc)
...@@ -2517,7 +2469,6 @@ static int qeth_l3_recover(void *ptr) ...@@ -2517,7 +2469,6 @@ static int qeth_l3_recover(void *ptr)
dev_warn(&card->gdev->dev, "The qeth device driver " dev_warn(&card->gdev->dev, "The qeth device driver "
"failed to recover an error on the device\n"); "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_start_bit(card, QETH_RECOVER_THREAD);
qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD); qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
return 0; return 0;
...@@ -2527,7 +2478,6 @@ static int qeth_l3_pm_suspend(struct ccwgroup_device *gdev) ...@@ -2527,7 +2478,6 @@ static int qeth_l3_pm_suspend(struct ccwgroup_device *gdev)
{ {
struct qeth_card *card = dev_get_drvdata(&gdev->dev); struct qeth_card *card = dev_get_drvdata(&gdev->dev);
netif_device_detach(card->dev);
qeth_set_allowed_threads(card, 0, 1); qeth_set_allowed_threads(card, 0, 1);
wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0); wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
if (gdev->state == CCWGROUP_OFFLINE) if (gdev->state == CCWGROUP_OFFLINE)
...@@ -2557,7 +2507,6 @@ static int qeth_l3_pm_resume(struct ccwgroup_device *gdev) ...@@ -2557,7 +2507,6 @@ static int qeth_l3_pm_resume(struct ccwgroup_device *gdev)
rc = __qeth_l3_set_online(card->gdev, 0); rc = __qeth_l3_set_online(card->gdev, 0);
qeth_set_allowed_threads(card, 0xffffffff, 0); qeth_set_allowed_threads(card, 0xffffffff, 0);
netif_device_attach(card->dev);
if (rc) if (rc)
dev_warn(&card->gdev->dev, "The qeth device driver " dev_warn(&card->gdev->dev, "The qeth device driver "
"failed to recover an error on the device\n"); "failed to recover an error on the device\n");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment