Commit f2bcf9dd authored by Julian Wiedmann's avatar Julian Wiedmann Committed by David S. Miller

s390/qeth: consolidate teardown code

Clarify which discipline-specific steps are needed to roll back after
error in qeth_l?_set_online(), and which are common to roll back
from qeth_hardsetup_card().

Some steps (cancelling the RX modeset, draining the TX queues) are only
necessary if the netdev was potentially UP before, so move them to the
common qeth_set_offline().
Signed-off-by: default avatarJulian Wiedmann <jwi@linux.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b7ea041b
...@@ -1062,11 +1062,7 @@ void qeth_notify_cmd(struct qeth_cmd_buffer *iob, int reason); ...@@ -1062,11 +1062,7 @@ void qeth_notify_cmd(struct qeth_cmd_buffer *iob, int reason);
void qeth_put_cmd(struct qeth_cmd_buffer *iob); void qeth_put_cmd(struct qeth_cmd_buffer *iob);
int qeth_schedule_recovery(struct qeth_card *card); int qeth_schedule_recovery(struct qeth_card *card);
void qeth_flush_local_addrs(struct qeth_card *card);
int qeth_poll(struct napi_struct *napi, int budget); int qeth_poll(struct napi_struct *napi, int budget);
int qeth_qdio_clear_card(struct qeth_card *, int);
void qeth_clear_working_pool_list(struct qeth_card *);
void qeth_drain_output_queues(struct qeth_card *card);
void qeth_setadp_promisc_mode(struct qeth_card *card, bool enable); void qeth_setadp_promisc_mode(struct qeth_card *card, bool enable);
int qeth_setadpparms_change_macaddr(struct qeth_card *); int qeth_setadpparms_change_macaddr(struct qeth_card *);
void qeth_tx_timeout(struct net_device *, unsigned int txqueue); void qeth_tx_timeout(struct net_device *, unsigned int txqueue);
......
...@@ -201,7 +201,7 @@ int qeth_threads_running(struct qeth_card *card, unsigned long threads) ...@@ -201,7 +201,7 @@ int qeth_threads_running(struct qeth_card *card, unsigned long threads)
} }
EXPORT_SYMBOL_GPL(qeth_threads_running); EXPORT_SYMBOL_GPL(qeth_threads_running);
void qeth_clear_working_pool_list(struct qeth_card *card) static 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;
struct qeth_qdio_q *queue = card->qdio.in_q; struct qeth_qdio_q *queue = card->qdio.in_q;
...@@ -216,7 +216,6 @@ void qeth_clear_working_pool_list(struct qeth_card *card) ...@@ -216,7 +216,6 @@ void qeth_clear_working_pool_list(struct qeth_card *card)
for (i = 0; i < ARRAY_SIZE(queue->bufs); i++) for (i = 0; i < ARRAY_SIZE(queue->bufs); i++)
queue->bufs[i].pool_entry = NULL; queue->bufs[i].pool_entry = NULL;
} }
EXPORT_SYMBOL_GPL(qeth_clear_working_pool_list);
static void qeth_free_pool_entry(struct qeth_buffer_pool_entry *entry) static void qeth_free_pool_entry(struct qeth_buffer_pool_entry *entry)
{ {
...@@ -658,12 +657,11 @@ static void qeth_flush_local_addrs6(struct qeth_card *card) ...@@ -658,12 +657,11 @@ static void qeth_flush_local_addrs6(struct qeth_card *card)
spin_unlock_irq(&card->local_addrs6_lock); spin_unlock_irq(&card->local_addrs6_lock);
} }
void qeth_flush_local_addrs(struct qeth_card *card) static void qeth_flush_local_addrs(struct qeth_card *card)
{ {
qeth_flush_local_addrs4(card); qeth_flush_local_addrs4(card);
qeth_flush_local_addrs6(card); qeth_flush_local_addrs6(card);
} }
EXPORT_SYMBOL_GPL(qeth_flush_local_addrs);
static void qeth_add_local_addrs4(struct qeth_card *card, static void qeth_add_local_addrs4(struct qeth_card *card,
struct qeth_ipacmd_local_addrs4 *cmd) struct qeth_ipacmd_local_addrs4 *cmd)
...@@ -1501,7 +1499,7 @@ static void qeth_drain_output_queue(struct qeth_qdio_out_q *q, bool free) ...@@ -1501,7 +1499,7 @@ static void qeth_drain_output_queue(struct qeth_qdio_out_q *q, bool free)
} }
} }
void qeth_drain_output_queues(struct qeth_card *card) static void qeth_drain_output_queues(struct qeth_card *card)
{ {
int i; int i;
...@@ -1512,7 +1510,6 @@ void qeth_drain_output_queues(struct qeth_card *card) ...@@ -1512,7 +1510,6 @@ void qeth_drain_output_queues(struct qeth_card *card)
qeth_drain_output_queue(card->qdio.out_qs[i], false); qeth_drain_output_queue(card->qdio.out_qs[i], false);
} }
} }
EXPORT_SYMBOL_GPL(qeth_drain_output_queues);
static int qeth_osa_set_output_queues(struct qeth_card *card, bool single) static int qeth_osa_set_output_queues(struct qeth_card *card, bool single)
{ {
...@@ -1840,7 +1837,7 @@ static int qeth_clear_halt_card(struct qeth_card *card, int halt) ...@@ -1840,7 +1837,7 @@ static int qeth_clear_halt_card(struct qeth_card *card, int halt)
return qeth_clear_channels(card); return qeth_clear_channels(card);
} }
int qeth_qdio_clear_card(struct qeth_card *card, int use_halt) static int qeth_qdio_clear_card(struct qeth_card *card, int use_halt)
{ {
int rc = 0; int rc = 0;
...@@ -1868,7 +1865,6 @@ int qeth_qdio_clear_card(struct qeth_card *card, int use_halt) ...@@ -1868,7 +1865,6 @@ int qeth_qdio_clear_card(struct qeth_card *card, int use_halt)
QETH_CARD_TEXT_(card, 3, "2err%d", rc); QETH_CARD_TEXT_(card, 3, "2err%d", rc);
return rc; return rc;
} }
EXPORT_SYMBOL_GPL(qeth_qdio_clear_card);
static enum qeth_discipline_id qeth_vm_detect_layer(struct qeth_card *card) static enum qeth_discipline_id qeth_vm_detect_layer(struct qeth_card *card)
{ {
...@@ -5333,6 +5329,10 @@ static int qeth_set_online(struct qeth_card *card) ...@@ -5333,6 +5329,10 @@ static int qeth_set_online(struct qeth_card *card)
err_online: err_online:
err_hardsetup: err_hardsetup:
qeth_qdio_clear_card(card, 0);
qeth_clear_working_pool_list(card);
qeth_flush_local_addrs(card);
qeth_stop_channel(&card->data); qeth_stop_channel(&card->data);
qeth_stop_channel(&card->write); qeth_stop_channel(&card->write);
qeth_stop_channel(&card->read); qeth_stop_channel(&card->read);
...@@ -5366,8 +5366,16 @@ int qeth_set_offline(struct qeth_card *card, bool resetting) ...@@ -5366,8 +5366,16 @@ int qeth_set_offline(struct qeth_card *card, bool resetting)
netif_carrier_off(card->dev); netif_carrier_off(card->dev);
rtnl_unlock(); rtnl_unlock();
cancel_work_sync(&card->rx_mode_work);
card->discipline->set_offline(card); card->discipline->set_offline(card);
qeth_qdio_clear_card(card, 0);
qeth_drain_output_queues(card);
qeth_clear_working_pool_list(card);
qeth_flush_local_addrs(card);
card->info.promisc_mode = 0;
rc = qeth_stop_channel(&card->data); rc = qeth_stop_channel(&card->data);
rc2 = qeth_stop_channel(&card->write); rc2 = qeth_stop_channel(&card->write);
rc3 = qeth_stop_channel(&card->read); rc3 = qeth_stop_channel(&card->read);
......
...@@ -304,34 +304,6 @@ static void qeth_l2_dev2br_fdb_flush(struct qeth_card *card) ...@@ -304,34 +304,6 @@ static void qeth_l2_dev2br_fdb_flush(struct qeth_card *card)
card->dev, &info.info, NULL); card->dev, &info.info, NULL);
} }
static void qeth_l2_stop_card(struct qeth_card *card)
{
struct qeth_priv *priv = netdev_priv(card->dev);
QETH_CARD_TEXT(card, 2, "stopcard");
qeth_set_allowed_threads(card, 0, 1);
cancel_work_sync(&card->rx_mode_work);
qeth_l2_drain_rx_mode_cache(card);
if (card->state == CARD_STATE_SOFTSETUP)
card->state = CARD_STATE_DOWN;
qeth_qdio_clear_card(card, 0);
qeth_drain_output_queues(card);
qeth_clear_working_pool_list(card);
qeth_l2_set_pnso_mode(card, QETH_PNSO_NONE);
qeth_flush_local_addrs(card);
card->info.promisc_mode = 0;
if (priv->brport_features & BR_LEARNING_SYNC) {
rtnl_lock();
qeth_l2_dev2br_fdb_flush(card);
rtnl_unlock();
}
}
static int qeth_l2_request_initial_mac(struct qeth_card *card) static int qeth_l2_request_initial_mac(struct qeth_card *card)
{ {
int rc = 0; int rc = 0;
...@@ -1172,7 +1144,7 @@ static int qeth_l2_set_online(struct qeth_card *card, bool carrier_ok) ...@@ -1172,7 +1144,7 @@ static int qeth_l2_set_online(struct qeth_card *card, bool carrier_ok)
if (dev->reg_state != NETREG_REGISTERED) { if (dev->reg_state != NETREG_REGISTERED) {
rc = qeth_l2_setup_netdev(card); rc = qeth_l2_setup_netdev(card);
if (rc) if (rc)
goto out_remove; goto err_setup;
if (carrier_ok) if (carrier_ok)
netif_carrier_on(dev); netif_carrier_on(dev);
...@@ -1195,14 +1167,28 @@ static int qeth_l2_set_online(struct qeth_card *card, bool carrier_ok) ...@@ -1195,14 +1167,28 @@ static int qeth_l2_set_online(struct qeth_card *card, bool carrier_ok)
} }
return 0; return 0;
out_remove: err_setup:
qeth_l2_stop_card(card); qeth_set_allowed_threads(card, 0, 1);
card->state = CARD_STATE_DOWN;
return rc; return rc;
} }
static void qeth_l2_set_offline(struct qeth_card *card) static void qeth_l2_set_offline(struct qeth_card *card)
{ {
qeth_l2_stop_card(card); struct qeth_priv *priv = netdev_priv(card->dev);
qeth_set_allowed_threads(card, 0, 1);
qeth_l2_drain_rx_mode_cache(card);
if (card->state == CARD_STATE_SOFTSETUP)
card->state = CARD_STATE_DOWN;
qeth_l2_set_pnso_mode(card, QETH_PNSO_NONE);
if (priv->brport_features & BR_LEARNING_SYNC) {
rtnl_lock();
qeth_l2_dev2br_fdb_flush(card);
rtnl_unlock();
}
} }
static int __init qeth_l2_init(void) static int __init qeth_l2_init(void)
......
...@@ -1142,32 +1142,6 @@ static int qeth_l3_vlan_rx_kill_vid(struct net_device *dev, ...@@ -1142,32 +1142,6 @@ static int qeth_l3_vlan_rx_kill_vid(struct net_device *dev,
return 0; return 0;
} }
static void qeth_l3_stop_card(struct qeth_card *card)
{
QETH_CARD_TEXT(card, 2, "stopcard");
qeth_set_allowed_threads(card, 0, 1);
cancel_work_sync(&card->rx_mode_work);
qeth_l3_drain_rx_mode_cache(card);
if (card->options.sniffer &&
(card->info.promisc_mode == SET_PROMISC_MODE_ON))
qeth_diags_trace(card, QETH_DIAGS_CMD_TRACE_DISABLE);
if (card->state == CARD_STATE_SOFTSETUP) {
card->state = CARD_STATE_DOWN;
qeth_l3_clear_ip_htable(card, 1);
}
qeth_qdio_clear_card(card, 0);
qeth_drain_output_queues(card);
qeth_clear_working_pool_list(card);
flush_workqueue(card->event_wq);
qeth_flush_local_addrs(card);
card->info.promisc_mode = 0;
}
static void qeth_l3_set_promisc_mode(struct qeth_card *card) static void qeth_l3_set_promisc_mode(struct qeth_card *card)
{ {
bool enable = card->dev->flags & IFF_PROMISC; bool enable = card->dev->flags & IFF_PROMISC;
...@@ -2042,7 +2016,7 @@ static int qeth_l3_set_online(struct qeth_card *card, bool carrier_ok) ...@@ -2042,7 +2016,7 @@ static int qeth_l3_set_online(struct qeth_card *card, bool carrier_ok)
if (dev->reg_state != NETREG_REGISTERED) { if (dev->reg_state != NETREG_REGISTERED) {
rc = qeth_l3_setup_netdev(card); rc = qeth_l3_setup_netdev(card);
if (rc) if (rc)
goto out_remove; goto err_setup;
if (carrier_ok) if (carrier_ok)
netif_carrier_on(dev); netif_carrier_on(dev);
...@@ -2064,14 +2038,26 @@ static int qeth_l3_set_online(struct qeth_card *card, bool carrier_ok) ...@@ -2064,14 +2038,26 @@ static int qeth_l3_set_online(struct qeth_card *card, bool carrier_ok)
} }
return 0; return 0;
out_remove: err_setup:
qeth_l3_stop_card(card); qeth_set_allowed_threads(card, 0, 1);
card->state = CARD_STATE_DOWN;
qeth_l3_clear_ip_htable(card, 1);
return rc; return rc;
} }
static void qeth_l3_set_offline(struct qeth_card *card) static void qeth_l3_set_offline(struct qeth_card *card)
{ {
qeth_l3_stop_card(card); qeth_set_allowed_threads(card, 0, 1);
qeth_l3_drain_rx_mode_cache(card);
if (card->options.sniffer &&
(card->info.promisc_mode == SET_PROMISC_MODE_ON))
qeth_diags_trace(card, QETH_DIAGS_CMD_TRACE_DISABLE);
if (card->state == CARD_STATE_SOFTSETUP) {
card->state = CARD_STATE_DOWN;
qeth_l3_clear_ip_htable(card, 1);
}
} }
/* Returns zero if the command is successfully "consumed" */ /* Returns zero if the command is successfully "consumed" */
......
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