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)
......
This diff is collapsed.
...@@ -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