aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/net/qeth.h
diff options
context:
space:
mode:
authorFrank Pavlic <fpavlic@de.ibm.com>2006-09-15 10:26:19 -0400
committerJeff Garzik <jeff@garzik.org>2006-09-17 01:03:07 -0400
commitf7b65d70a3e6f1c97eb614964270816992d0d4b4 (patch)
treefae68b2d6c215abacd3074b81bc320f5b3e3a0e0 /drivers/s390/net/qeth.h
parent1fda1a120b7dcddf382ad105b4783a69e81c7a2b (diff)
[PATCH] s390: qeth driver fixes [3/6]
[PATCH 6/9] s390: qeth driver fixes [3/6] From: Frank Pavlic <fpavlic@de.ibm.com> fixed kernel panic caused by qeth driver: Using a bonding device qeth driver will realloc headroom for every skb coming from the bond device. Once this happens qeth frees the original skb and set the skb pointer to the new realloced skb. Under heavy transmit workload (e.g.UDP streams) through bond network device the qdio output queue might get full. In this case we return with EBUSY from qeth_send_packet. Returning to qeth_hard_start_xmit routine the skb address on the stack still points to the old address, which has been freed before. Returning from qeth_hard_start_xmit with EBUSY results in requeuing the skb. In this case it corrupts the qdisc queue and results in kernel panic. Signed-off-by: Frank Pavlic <fpavlic@de.ibm.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/s390/net/qeth.h')
-rw-r--r--drivers/s390/net/qeth.h35
1 files changed, 14 insertions, 21 deletions
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index e8bd8c5ced1f..c04ee915dc1b 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -859,23 +859,18 @@ qeth_get_ipa_adp_type(enum qeth_link_types link_type)
859 } 859 }
860} 860}
861 861
862static inline int 862static inline struct sk_buff *
863qeth_realloc_headroom(struct qeth_card *card, struct sk_buff **skb, int size) 863qeth_realloc_headroom(struct qeth_card *card, struct sk_buff *skb, int size)
864{ 864{
865 struct sk_buff *new_skb = NULL; 865 struct sk_buff *new_skb = skb;
866 866
867 if (skb_headroom(*skb) < size){ 867 if (skb_headroom(skb) >= size)
868 new_skb = skb_realloc_headroom(*skb, size); 868 return skb;
869 if (!new_skb) { 869 new_skb = skb_realloc_headroom(skb, size);
870 PRINT_ERR("qeth_prepare_skb: could " 870 if (!new_skb)
871 "not realloc headroom for qeth_hdr " 871 PRINT_ERR("Could not realloc headroom for qeth_hdr "
872 "on interface %s", QETH_CARD_IFNAME(card)); 872 "on interface %s", QETH_CARD_IFNAME(card));
873 return -ENOMEM; 873 return new_skb;
874 }
875 kfree_skb(*skb);
876 *skb = new_skb;
877 }
878 return 0;
879} 874}
880 875
881static inline struct sk_buff * 876static inline struct sk_buff *
@@ -885,16 +880,15 @@ qeth_pskb_unshare(struct sk_buff *skb, int pri)
885 if (!skb_cloned(skb)) 880 if (!skb_cloned(skb))
886 return skb; 881 return skb;
887 nskb = skb_copy(skb, pri); 882 nskb = skb_copy(skb, pri);
888 kfree_skb(skb); /* free our shared copy */
889 return nskb; 883 return nskb;
890} 884}
891 885
892static inline void * 886static inline void *
893qeth_push_skb(struct qeth_card *card, struct sk_buff **skb, int size) 887qeth_push_skb(struct qeth_card *card, struct sk_buff *skb, int size)
894{ 888{
895 void *hdr; 889 void *hdr;
896 890
897 hdr = (void *) skb_push(*skb, size); 891 hdr = (void *) skb_push(skb, size);
898 /* 892 /*
899 * sanity check, the Linux memory allocation scheme should 893 * sanity check, the Linux memory allocation scheme should
900 * never present us cases like this one (the qdio header size plus 894 * never present us cases like this one (the qdio header size plus
@@ -903,8 +897,7 @@ qeth_push_skb(struct qeth_card *card, struct sk_buff **skb, int size)
903 if ((((unsigned long) hdr) & (~(PAGE_SIZE - 1))) != 897 if ((((unsigned long) hdr) & (~(PAGE_SIZE - 1))) !=
904 (((unsigned long) hdr + size + 898 (((unsigned long) hdr + size +
905 QETH_IP_HEADER_SIZE) & (~(PAGE_SIZE - 1)))) { 899 QETH_IP_HEADER_SIZE) & (~(PAGE_SIZE - 1)))) {
906 PRINT_ERR("qeth_prepare_skb: misaligned " 900 PRINT_ERR("Misaligned packet on interface %s. Discarded.",
907 "packet on interface %s. Discarded.",
908 QETH_CARD_IFNAME(card)); 901 QETH_CARD_IFNAME(card));
909 return NULL; 902 return NULL;
910 } 903 }