s390/qeth: clean up Output Queue selection
Consolidate duplicated code, fix the misuse of RTN_UNSPEC and simplify the handling of non-unicast traffic on IQD devices. Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
9aa17df3b8
Коммит
86c0cdb9e0
|
@ -661,7 +661,6 @@ struct qeth_card_info {
|
||||||
int portno;
|
int portno;
|
||||||
enum qeth_card_types type;
|
enum qeth_card_types type;
|
||||||
enum qeth_link_types link_type;
|
enum qeth_link_types link_type;
|
||||||
int is_multicast_different;
|
|
||||||
int initial_mtu;
|
int initial_mtu;
|
||||||
int max_mtu;
|
int max_mtu;
|
||||||
int broadcast_capable;
|
int broadcast_capable;
|
||||||
|
@ -934,6 +933,19 @@ static inline int qeth_send_simple_setassparms_v6(struct qeth_card *card,
|
||||||
data, QETH_PROT_IPV6);
|
data, QETH_PROT_IPV6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb,
|
||||||
|
int ipv);
|
||||||
|
static inline struct qeth_qdio_out_q *qeth_get_tx_queue(struct qeth_card *card,
|
||||||
|
struct sk_buff *skb,
|
||||||
|
int ipv, int cast_type)
|
||||||
|
{
|
||||||
|
if (IS_IQD(card) && cast_type != RTN_UNICAST)
|
||||||
|
return card->qdio.out_qs[card->qdio.no_out_queues - 1];
|
||||||
|
if (!card->qdio.do_prio_queueing)
|
||||||
|
return card->qdio.out_qs[card->qdio.default_out_queue];
|
||||||
|
return card->qdio.out_qs[qeth_get_priority_queue(card, skb, ipv)];
|
||||||
|
}
|
||||||
|
|
||||||
extern struct qeth_discipline qeth_l2_discipline;
|
extern struct qeth_discipline qeth_l2_discipline;
|
||||||
extern struct qeth_discipline qeth_l3_discipline;
|
extern struct qeth_discipline qeth_l3_discipline;
|
||||||
extern const struct attribute_group *qeth_generic_attr_groups[];
|
extern const struct attribute_group *qeth_generic_attr_groups[];
|
||||||
|
@ -1001,7 +1013,6 @@ int qeth_bridgeport_query_ports(struct qeth_card *card,
|
||||||
enum qeth_sbp_roles *role, enum qeth_sbp_states *state);
|
enum qeth_sbp_roles *role, enum qeth_sbp_states *state);
|
||||||
int qeth_bridgeport_setrole(struct qeth_card *card, enum qeth_sbp_roles role);
|
int qeth_bridgeport_setrole(struct qeth_card *card, enum qeth_sbp_roles role);
|
||||||
int qeth_bridgeport_an_set(struct qeth_card *card, int enable);
|
int qeth_bridgeport_an_set(struct qeth_card *card, int enable);
|
||||||
int qeth_get_priority_queue(struct qeth_card *, struct sk_buff *, int, int);
|
|
||||||
int qeth_get_elements_no(struct qeth_card *card, struct sk_buff *skb,
|
int qeth_get_elements_no(struct qeth_card *card, struct sk_buff *skb,
|
||||||
int extra_elems, int data_offset);
|
int extra_elems, int data_offset);
|
||||||
int qeth_get_elements_for_frags(struct sk_buff *);
|
int qeth_get_elements_for_frags(struct sk_buff *);
|
||||||
|
|
|
@ -1537,8 +1537,6 @@ static void qeth_determine_card_type(struct qeth_card *card)
|
||||||
card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
|
card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
|
||||||
card->info.type = CARD_RDEV(card)->id.driver_info;
|
card->info.type = CARD_RDEV(card)->id.driver_info;
|
||||||
card->qdio.no_out_queues = QETH_MAX_QUEUES;
|
card->qdio.no_out_queues = QETH_MAX_QUEUES;
|
||||||
if (card->info.type == QETH_CARD_TYPE_IQD)
|
|
||||||
card->info.is_multicast_different = 0x0103;
|
|
||||||
qeth_update_from_chp_desc(card);
|
qeth_update_from_chp_desc(card);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3777,15 +3775,11 @@ static inline int qeth_cut_iqd_prio(struct qeth_card *card, int queue_num)
|
||||||
* Note: Function assumes that we have 4 outbound queues.
|
* Note: Function assumes that we have 4 outbound queues.
|
||||||
*/
|
*/
|
||||||
int qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb,
|
int qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb,
|
||||||
int ipv, int cast_type)
|
int ipv)
|
||||||
{
|
{
|
||||||
__be16 *tci;
|
__be16 *tci;
|
||||||
u8 tos;
|
u8 tos;
|
||||||
|
|
||||||
if (cast_type && card->info.is_multicast_different)
|
|
||||||
return card->info.is_multicast_different &
|
|
||||||
(card->qdio.no_out_queues - 1);
|
|
||||||
|
|
||||||
switch (card->qdio.do_prio_queueing) {
|
switch (card->qdio.do_prio_queueing) {
|
||||||
case QETH_PRIO_Q_ING_TOS:
|
case QETH_PRIO_Q_ING_TOS:
|
||||||
case QETH_PRIO_Q_ING_PREC:
|
case QETH_PRIO_Q_ING_PREC:
|
||||||
|
|
|
@ -64,6 +64,8 @@ enum qeth_card_types {
|
||||||
QETH_CARD_TYPE_OSX = 2,
|
QETH_CARD_TYPE_OSX = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define IS_IQD(card) ((card)->info.type == QETH_CARD_TYPE_IQD)
|
||||||
|
|
||||||
#define QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE 0x18
|
#define QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE 0x18
|
||||||
/* only the first two bytes are looked at in qeth_get_cardname_short */
|
/* only the first two bytes are looked at in qeth_get_cardname_short */
|
||||||
enum qeth_link_types {
|
enum qeth_link_types {
|
||||||
|
|
|
@ -185,12 +185,12 @@ static void qeth_l2_del_all_macs(struct qeth_card *card)
|
||||||
static int qeth_l2_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
|
static int qeth_l2_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
if (card->info.type == QETH_CARD_TYPE_OSN)
|
if (card->info.type == QETH_CARD_TYPE_OSN)
|
||||||
return RTN_UNSPEC;
|
return RTN_UNICAST;
|
||||||
if (is_broadcast_ether_addr(skb->data))
|
if (is_broadcast_ether_addr(skb->data))
|
||||||
return RTN_BROADCAST;
|
return RTN_BROADCAST;
|
||||||
if (is_multicast_ether_addr(skb->data))
|
if (is_multicast_ether_addr(skb->data))
|
||||||
return RTN_MULTICAST;
|
return RTN_MULTICAST;
|
||||||
return RTN_UNSPEC;
|
return RTN_UNICAST;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qeth_l2_fill_header(struct qeth_hdr *hdr, struct sk_buff *skb,
|
static void qeth_l2_fill_header(struct qeth_hdr *hdr, struct sk_buff *skb,
|
||||||
|
@ -768,18 +768,13 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb,
|
||||||
int tx_bytes = skb->len;
|
int tx_bytes = skb->len;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (card->qdio.do_prio_queueing || (cast_type &&
|
|
||||||
card->info.is_multicast_different))
|
|
||||||
queue = card->qdio.out_qs[qeth_get_priority_queue(card, skb,
|
|
||||||
ipv, cast_type)];
|
|
||||||
else
|
|
||||||
queue = card->qdio.out_qs[card->qdio.default_out_queue];
|
|
||||||
|
|
||||||
if ((card->state != CARD_STATE_UP) || !card->lan_online) {
|
if ((card->state != CARD_STATE_UP) || !card->lan_online) {
|
||||||
card->stats.tx_carrier_errors++;
|
card->stats.tx_carrier_errors++;
|
||||||
goto tx_drop;
|
goto tx_drop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
queue = qeth_get_tx_queue(card, skb, ipv, cast_type);
|
||||||
|
|
||||||
if (card->options.performance_stats) {
|
if (card->options.performance_stats) {
|
||||||
card->perf_stats.outbound_cnt++;
|
card->perf_stats.outbound_cnt++;
|
||||||
card->perf_stats.outbound_start_time = qeth_get_micros();
|
card->perf_stats.outbound_start_time = qeth_get_micros();
|
||||||
|
|
|
@ -1978,17 +1978,17 @@ static int qeth_l3_get_cast_type(struct sk_buff *skb)
|
||||||
(cast_type == RTN_MULTICAST) ||
|
(cast_type == RTN_MULTICAST) ||
|
||||||
(cast_type == RTN_ANYCAST))
|
(cast_type == RTN_ANYCAST))
|
||||||
return cast_type;
|
return cast_type;
|
||||||
return RTN_UNSPEC;
|
return RTN_UNICAST;
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
/* no neighbour (eg AF_PACKET), fall back to target's IP address ... */
|
/* no neighbour (eg AF_PACKET), fall back to target's IP address ... */
|
||||||
if (be16_to_cpu(skb->protocol) == ETH_P_IPV6)
|
if (be16_to_cpu(skb->protocol) == ETH_P_IPV6)
|
||||||
return ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) ?
|
return ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) ?
|
||||||
RTN_MULTICAST : RTN_UNSPEC;
|
RTN_MULTICAST : RTN_UNICAST;
|
||||||
else if (be16_to_cpu(skb->protocol) == ETH_P_IP)
|
else if (be16_to_cpu(skb->protocol) == ETH_P_IP)
|
||||||
return ipv4_is_multicast(ip_hdr(skb)->daddr) ?
|
return ipv4_is_multicast(ip_hdr(skb)->daddr) ?
|
||||||
RTN_MULTICAST : RTN_UNSPEC;
|
RTN_MULTICAST : RTN_UNICAST;
|
||||||
|
|
||||||
/* ... and MAC address */
|
/* ... and MAC address */
|
||||||
if (ether_addr_equal_64bits(eth_hdr(skb)->h_dest, skb->dev->broadcast))
|
if (ether_addr_equal_64bits(eth_hdr(skb)->h_dest, skb->dev->broadcast))
|
||||||
|
@ -1997,7 +1997,7 @@ static int qeth_l3_get_cast_type(struct sk_buff *skb)
|
||||||
return RTN_MULTICAST;
|
return RTN_MULTICAST;
|
||||||
|
|
||||||
/* default to unicast */
|
/* default to unicast */
|
||||||
return RTN_UNSPEC;
|
return RTN_UNICAST;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qeth_l3_fill_af_iucv_hdr(struct qeth_card *card,
|
static void qeth_l3_fill_af_iucv_hdr(struct qeth_card *card,
|
||||||
|
@ -2168,11 +2168,7 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
|
||||||
struct sk_buff *new_skb = NULL;
|
struct sk_buff *new_skb = NULL;
|
||||||
int ipv = qeth_get_ip_version(skb);
|
int ipv = qeth_get_ip_version(skb);
|
||||||
int cast_type = qeth_l3_get_cast_type(skb);
|
int cast_type = qeth_l3_get_cast_type(skb);
|
||||||
struct qeth_qdio_out_q *queue =
|
struct qeth_qdio_out_q *queue;
|
||||||
card->qdio.out_qs[card->qdio.do_prio_queueing
|
|
||||||
|| (cast_type && card->info.is_multicast_different) ?
|
|
||||||
qeth_get_priority_queue(card, skb, ipv, cast_type) :
|
|
||||||
card->qdio.default_out_queue];
|
|
||||||
int tx_bytes = skb->len;
|
int tx_bytes = skb->len;
|
||||||
unsigned int hd_len = 0;
|
unsigned int hd_len = 0;
|
||||||
bool use_tso;
|
bool use_tso;
|
||||||
|
@ -2195,6 +2191,8 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
|
||||||
(card->info.broadcast_capable == 0))
|
(card->info.broadcast_capable == 0))
|
||||||
goto tx_drop;
|
goto tx_drop;
|
||||||
|
|
||||||
|
queue = qeth_get_tx_queue(card, skb, ipv, cast_type);
|
||||||
|
|
||||||
if (card->options.performance_stats) {
|
if (card->options.performance_stats) {
|
||||||
card->perf_stats.outbound_cnt++;
|
card->perf_stats.outbound_cnt++;
|
||||||
card->perf_stats.outbound_start_time = qeth_get_micros();
|
card->perf_stats.outbound_start_time = qeth_get_micros();
|
||||||
|
|
Загрузка…
Ссылка в новой задаче