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

s390/qeth: support per-frame invalidation

Each RX buffer may contain up to 64KB worth of data. In case the device
needs to discard a packet _after_ already having reserved space for it
in the buffer, the whole buffer gets set to ERROR state. As the buffer
might contain any number of good packets, this can result in collateral
packet loss.

qeth can provide relief by enabling per-frame invalidation. The RX
buffer is then presented as usual, we just need to spot & drop any
individual packet that was flagged as invalid.
Signed-off-by: default avatarJulian Wiedmann <jwi@linux.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 845ef904
...@@ -368,6 +368,7 @@ enum qeth_header_ids { ...@@ -368,6 +368,7 @@ enum qeth_header_ids {
QETH_HEADER_TYPE_L3_TSO = 0x03, QETH_HEADER_TYPE_L3_TSO = 0x03,
QETH_HEADER_TYPE_OSN = 0x04, QETH_HEADER_TYPE_OSN = 0x04,
QETH_HEADER_TYPE_L2_TSO = 0x06, QETH_HEADER_TYPE_L2_TSO = 0x06,
QETH_HEADER_MASK_INVAL = 0x80,
}; };
/* flags for qeth_hdr.ext_flags */ /* flags for qeth_hdr.ext_flags */
#define QETH_HDR_EXT_VLAN_FRAME 0x01 #define QETH_HDR_EXT_VLAN_FRAME 0x01
...@@ -485,6 +486,7 @@ struct qeth_card_stats { ...@@ -485,6 +486,7 @@ struct qeth_card_stats {
u64 rx_bytes; u64 rx_bytes;
u64 rx_multicast; u64 rx_multicast;
u64 rx_length_errors; u64 rx_length_errors;
u64 rx_frame_errors;
u64 rx_fifo_errors; u64 rx_fifo_errors;
}; };
......
...@@ -1956,6 +1956,7 @@ static void qeth_idx_setup_activate_cmd(struct qeth_card *card, ...@@ -1956,6 +1956,7 @@ static void qeth_idx_setup_activate_cmd(struct qeth_card *card,
ccw_device_get_id(CARD_DDEV(card), &dev_id); ccw_device_get_id(CARD_DDEV(card), &dev_id);
iob->finalize = qeth_idx_finalize_cmd; iob->finalize = qeth_idx_finalize_cmd;
port |= QETH_IDX_ACT_INVAL_FRAME;
memcpy(QETH_IDX_ACT_PNO(iob->data), &port, 1); memcpy(QETH_IDX_ACT_PNO(iob->data), &port, 1);
memcpy(QETH_IDX_ACT_ISSUER_RM_TOKEN(iob->data), memcpy(QETH_IDX_ACT_ISSUER_RM_TOKEN(iob->data),
&card->token.issuer_rm_w, QETH_MPC_TOKEN_LENGTH); &card->token.issuer_rm_w, QETH_MPC_TOKEN_LENGTH);
...@@ -4346,7 +4347,9 @@ static int qeth_mdio_read(struct net_device *dev, int phy_id, int regnum) ...@@ -4346,7 +4347,9 @@ static int qeth_mdio_read(struct net_device *dev, int phy_id, int regnum)
case MII_NWAYTEST: /* N-way auto-neg test register */ case MII_NWAYTEST: /* N-way auto-neg test register */
break; break;
case MII_RERRCOUNTER: /* rx error counter */ case MII_RERRCOUNTER: /* rx error counter */
rc = card->stats.rx_length_errors + card->stats.rx_fifo_errors; rc = card->stats.rx_length_errors +
card->stats.rx_frame_errors +
card->stats.rx_fifo_errors;
break; break;
case MII_SREVISION: /* silicon revision */ case MII_SREVISION: /* silicon revision */
break; break;
...@@ -5092,7 +5095,11 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card, ...@@ -5092,7 +5095,11 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card,
headroom = sizeof(struct qeth_hdr); headroom = sizeof(struct qeth_hdr);
break; break;
default: default:
QETH_CARD_STAT_INC(card, rx_dropped_notsupp); if ((*hdr)->hdr.l2.id & QETH_HEADER_MASK_INVAL)
QETH_CARD_STAT_INC(card, rx_frame_errors);
else
QETH_CARD_STAT_INC(card, rx_dropped_notsupp);
break; break;
} }
...@@ -6238,11 +6245,13 @@ void qeth_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) ...@@ -6238,11 +6245,13 @@ void qeth_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
stats->rx_packets = card->stats.rx_packets; stats->rx_packets = card->stats.rx_packets;
stats->rx_bytes = card->stats.rx_bytes; stats->rx_bytes = card->stats.rx_bytes;
stats->rx_errors = card->stats.rx_length_errors + stats->rx_errors = card->stats.rx_length_errors +
card->stats.rx_frame_errors +
card->stats.rx_fifo_errors; card->stats.rx_fifo_errors;
stats->rx_dropped = card->stats.rx_dropped_nomem + stats->rx_dropped = card->stats.rx_dropped_nomem +
card->stats.rx_dropped_notsupp; card->stats.rx_dropped_notsupp;
stats->multicast = card->stats.rx_multicast; stats->multicast = card->stats.rx_multicast;
stats->rx_length_errors = card->stats.rx_length_errors; stats->rx_length_errors = card->stats.rx_length_errors;
stats->rx_frame_errors = card->stats.rx_frame_errors;
stats->rx_fifo_errors = card->stats.rx_fifo_errors; stats->rx_fifo_errors = card->stats.rx_fifo_errors;
for (i = 0; i < card->qdio.no_out_queues; i++) { for (i = 0; i < card->qdio.no_out_queues; i++) {
......
...@@ -900,6 +900,7 @@ extern unsigned char IDX_ACTIVATE_WRITE[]; ...@@ -900,6 +900,7 @@ extern unsigned char IDX_ACTIVATE_WRITE[];
#define IDX_ACTIVATE_SIZE 0x22 #define IDX_ACTIVATE_SIZE 0x22
#define QETH_IDX_ACT_PNO(buffer) (buffer+0x0b) #define QETH_IDX_ACT_PNO(buffer) (buffer+0x0b)
#define QETH_IDX_ACT_ISSUER_RM_TOKEN(buffer) (buffer + 0x0c) #define QETH_IDX_ACT_ISSUER_RM_TOKEN(buffer) (buffer + 0x0c)
#define QETH_IDX_ACT_INVAL_FRAME 0x40
#define QETH_IDX_NO_PORTNAME_REQUIRED(buffer) ((buffer)[0x0b] & 0x80) #define QETH_IDX_NO_PORTNAME_REQUIRED(buffer) ((buffer)[0x0b] & 0x80)
#define QETH_IDX_ACT_FUNC_LEVEL(buffer) (buffer + 0x10) #define QETH_IDX_ACT_FUNC_LEVEL(buffer) (buffer + 0x10)
#define QETH_IDX_ACT_DATASET_NAME(buffer) (buffer + 0x16) #define QETH_IDX_ACT_DATASET_NAME(buffer) (buffer + 0x16)
......
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