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

s390/qeth: simplify max MTU handling

When the MPC initialization code discovers the HW-specific max MTU,
apply the resulting changes straight to the netdevice.

If this is the device's first initialization, also set its MTU
(HiperSockets: the max MTU; else: a layer-specific default value).
Then cap the current MTU by the new max MTU.
Signed-off-by: default avatarJulian Wiedmann <jwi@linux.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 92d27209
...@@ -660,8 +660,6 @@ struct qeth_card_info { ...@@ -660,8 +660,6 @@ struct qeth_card_info {
int mac_bits; int mac_bits;
enum qeth_card_types type; enum qeth_card_types type;
enum qeth_link_types link_type; enum qeth_link_types link_type;
int initial_mtu;
int max_mtu;
int broadcast_capable; int broadcast_capable;
int unique_id; int unique_id;
bool layer_enforced; bool layer_enforced;
......
...@@ -2278,19 +2278,42 @@ static int qeth_cm_setup(struct qeth_card *card) ...@@ -2278,19 +2278,42 @@ static int qeth_cm_setup(struct qeth_card *card)
} }
static int qeth_get_initial_mtu_for_card(struct qeth_card *card) static int qeth_update_max_mtu(struct qeth_card *card, unsigned int max_mtu)
{ {
switch (card->info.type) { struct net_device *dev = card->dev;
case QETH_CARD_TYPE_IQD: unsigned int new_mtu;
return card->info.max_mtu;
case QETH_CARD_TYPE_OSD: if (!max_mtu) {
case QETH_CARD_TYPE_OSX: /* IQD needs accurate max MTU to set up its RX buffers: */
if (!card->options.layer2) if (IS_IQD(card))
return ETH_DATA_LEN - 8; /* L3: allow for LLC + SNAP */ return -EINVAL;
/* fall through */ /* tolerate quirky HW: */
default: max_mtu = ETH_MAX_MTU;
return ETH_DATA_LEN;
} }
rtnl_lock();
if (IS_IQD(card)) {
/* move any device with default MTU to new max MTU: */
new_mtu = (dev->mtu == dev->max_mtu) ? max_mtu : dev->mtu;
/* adjust RX buffer size to new max MTU: */
card->qdio.in_buf_size = max_mtu + 2 * PAGE_SIZE;
if (dev->max_mtu && dev->max_mtu != max_mtu)
qeth_free_qdio_buffers(card);
} else {
if (dev->mtu)
new_mtu = dev->mtu;
/* default MTUs for first setup: */
else if (card->options.layer2)
new_mtu = ETH_DATA_LEN;
else
new_mtu = ETH_DATA_LEN - 8; /* allow for LLC + SNAP */
}
dev->max_mtu = max_mtu;
dev->mtu = min(new_mtu, max_mtu);
rtnl_unlock();
return 0;
} }
static int qeth_get_mtu_outof_framesize(int framesize) static int qeth_get_mtu_outof_framesize(int framesize)
...@@ -2316,8 +2339,7 @@ static int qeth_mtu_is_valid(struct qeth_card *card, int mtu) ...@@ -2316,8 +2339,7 @@ static int qeth_mtu_is_valid(struct qeth_card *card, int mtu)
case QETH_CARD_TYPE_OSM: case QETH_CARD_TYPE_OSM:
case QETH_CARD_TYPE_OSX: case QETH_CARD_TYPE_OSX:
case QETH_CARD_TYPE_IQD: case QETH_CARD_TYPE_IQD:
return ((mtu >= 576) && return ((mtu >= 576) && (mtu <= card->dev->max_mtu));
(mtu <= card->info.max_mtu));
case QETH_CARD_TYPE_OSN: case QETH_CARD_TYPE_OSN:
default: default:
return 1; return 1;
...@@ -2342,28 +2364,10 @@ static int qeth_ulp_enable_cb(struct qeth_card *card, struct qeth_reply *reply, ...@@ -2342,28 +2364,10 @@ static int qeth_ulp_enable_cb(struct qeth_card *card, struct qeth_reply *reply,
if (card->info.type == QETH_CARD_TYPE_IQD) { if (card->info.type == QETH_CARD_TYPE_IQD) {
memcpy(&framesize, QETH_ULP_ENABLE_RESP_MAX_MTU(iob->data), 2); memcpy(&framesize, QETH_ULP_ENABLE_RESP_MAX_MTU(iob->data), 2);
mtu = qeth_get_mtu_outof_framesize(framesize); mtu = qeth_get_mtu_outof_framesize(framesize);
if (!mtu) {
iob->rc = -EINVAL;
QETH_DBF_TEXT_(SETUP, 2, " rc%d", iob->rc);
return 0;
}
if (card->info.initial_mtu && (card->info.initial_mtu != mtu)) {
/* frame size has changed */
if ((card->dev->mtu == card->info.initial_mtu) ||
(card->dev->mtu > mtu))
card->dev->mtu = mtu;
qeth_free_qdio_buffers(card);
}
card->info.initial_mtu = mtu;
card->info.max_mtu = mtu;
card->qdio.in_buf_size = mtu + 2 * PAGE_SIZE;
} else { } else {
card->info.max_mtu = *(__u16 *)QETH_ULP_ENABLE_RESP_MAX_MTU( mtu = *(__u16 *)QETH_ULP_ENABLE_RESP_MAX_MTU(iob->data);
iob->data);
card->info.initial_mtu = min(card->info.max_mtu,
qeth_get_initial_mtu_for_card(card));
card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT;
} }
*(u16 *)reply->param = mtu;
memcpy(&len, QETH_ULP_ENABLE_RESP_DIFINFO_LEN(iob->data), 2); memcpy(&len, QETH_ULP_ENABLE_RESP_DIFINFO_LEN(iob->data), 2);
if (len >= QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE) { if (len >= QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE) {
...@@ -2382,6 +2386,7 @@ static int qeth_ulp_enable(struct qeth_card *card) ...@@ -2382,6 +2386,7 @@ static int qeth_ulp_enable(struct qeth_card *card)
int rc; int rc;
char prot_type; char prot_type;
struct qeth_cmd_buffer *iob; struct qeth_cmd_buffer *iob;
u16 max_mtu;
/*FIXME: trace view callbacks*/ /*FIXME: trace view callbacks*/
QETH_DBF_TEXT(SETUP, 2, "ulpenabl"); QETH_DBF_TEXT(SETUP, 2, "ulpenabl");
...@@ -2404,9 +2409,10 @@ static int qeth_ulp_enable(struct qeth_card *card) ...@@ -2404,9 +2409,10 @@ static int qeth_ulp_enable(struct qeth_card *card)
memcpy(QETH_ULP_ENABLE_FILTER_TOKEN(iob->data), memcpy(QETH_ULP_ENABLE_FILTER_TOKEN(iob->data),
&card->token.ulp_filter_w, QETH_MPC_TOKEN_LENGTH); &card->token.ulp_filter_w, QETH_MPC_TOKEN_LENGTH);
rc = qeth_send_control_data(card, ULP_ENABLE_SIZE, iob, rc = qeth_send_control_data(card, ULP_ENABLE_SIZE, iob,
qeth_ulp_enable_cb, NULL); qeth_ulp_enable_cb, &max_mtu);
if (rc)
return rc; return rc;
return qeth_update_max_mtu(card, max_mtu);
} }
static int qeth_ulp_setup_cb(struct qeth_card *card, struct qeth_reply *reply, static int qeth_ulp_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
...@@ -5691,7 +5697,9 @@ static struct net_device *qeth_alloc_netdev(struct qeth_card *card) ...@@ -5691,7 +5697,9 @@ static struct net_device *qeth_alloc_netdev(struct qeth_card *card)
dev->ml_priv = card; dev->ml_priv = card;
dev->watchdog_timeo = QETH_TX_TIMEOUT; dev->watchdog_timeo = QETH_TX_TIMEOUT;
dev->min_mtu = 64; dev->min_mtu = 64;
dev->max_mtu = ETH_MAX_MTU; /* initialized when device first goes online: */
dev->max_mtu = 0;
dev->mtu = 0;
SET_NETDEV_DEV(dev, &card->gdev->dev); SET_NETDEV_DEV(dev, &card->gdev->dev);
netif_carrier_off(dev); netif_carrier_off(dev);
return dev; return dev;
......
...@@ -944,7 +944,6 @@ static int qeth_l2_setup_netdev(struct qeth_card *card) ...@@ -944,7 +944,6 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
return 0; return 0;
card->dev->priv_flags |= IFF_UNICAST_FLT; card->dev->priv_flags |= IFF_UNICAST_FLT;
card->dev->mtu = card->info.initial_mtu;
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) {
card->dev->ethtool_ops = &qeth_l2_osn_ops; card->dev->ethtool_ops = &qeth_l2_osn_ops;
......
...@@ -2579,7 +2579,6 @@ static int qeth_l3_setup_netdev(struct qeth_card *card) ...@@ -2579,7 +2579,6 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
} else } else
return -ENODEV; return -ENODEV;
card->dev->mtu = card->info.initial_mtu;
card->dev->ethtool_ops = &qeth_l3_ethtool_ops; card->dev->ethtool_ops = &qeth_l3_ethtool_ops;
card->dev->priv_flags &= ~IFF_TX_SKB_SHARING; card->dev->priv_flags &= ~IFF_TX_SKB_SHARING;
card->dev->needed_headroom = sizeof(struct qeth_hdr) - ETH_HLEN; card->dev->needed_headroom = sizeof(struct qeth_hdr) - ETH_HLEN;
......
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