diff options
Diffstat (limited to 'drivers/s390/net/qeth_core_main.c')
| -rw-r--r-- | drivers/s390/net/qeth_core_main.c | 45 | 
1 files changed, 38 insertions, 7 deletions
| diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 0d8cdff8181..0d73a999983 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -3679,6 +3679,25 @@ int qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb,  }  EXPORT_SYMBOL_GPL(qeth_get_priority_queue); +int qeth_get_elements_for_frags(struct sk_buff *skb) +{ +	int cnt, length, e, elements = 0; +	struct skb_frag_struct *frag; +	char *data; + +	for (cnt = 0; cnt < skb_shinfo(skb)->nr_frags; cnt++) { +		frag = &skb_shinfo(skb)->frags[cnt]; +		data = (char *)page_to_phys(skb_frag_page(frag)) + +			frag->page_offset; +		length = frag->size; +		e = PFN_UP((unsigned long)data + length - 1) - +			PFN_DOWN((unsigned long)data); +		elements += e; +	} +	return elements; +} +EXPORT_SYMBOL_GPL(qeth_get_elements_for_frags); +  int qeth_get_elements_no(struct qeth_card *card, void *hdr,  		     struct sk_buff *skb, int elems)  { @@ -3686,7 +3705,8 @@ int qeth_get_elements_no(struct qeth_card *card, void *hdr,  	int elements_needed = PFN_UP((unsigned long)skb->data + dlen - 1) -  		PFN_DOWN((unsigned long)skb->data); -	elements_needed += skb_shinfo(skb)->nr_frags; +	elements_needed += qeth_get_elements_for_frags(skb); +  	if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)) {  		QETH_DBF_MESSAGE(2, "Invalid size of IP packet "  			"(Number=%d / Length=%d). Discarded.\n", @@ -3771,12 +3791,23 @@ static inline void __qeth_fill_buffer(struct sk_buff *skb,  	for (cnt = 0; cnt < skb_shinfo(skb)->nr_frags; cnt++) {  		frag = &skb_shinfo(skb)->frags[cnt]; -		buffer->element[element].addr = (char *) -			page_to_phys(skb_frag_page(frag)) -			+ frag->page_offset; -		buffer->element[element].length = frag->size; -		buffer->element[element].eflags = SBAL_EFLAGS_MIDDLE_FRAG; -		element++; +		data = (char *)page_to_phys(skb_frag_page(frag)) + +			frag->page_offset; +		length = frag->size; +		while (length > 0) { +			length_here = PAGE_SIZE - +				((unsigned long) data % PAGE_SIZE); +			if (length < length_here) +				length_here = length; + +			buffer->element[element].addr = data; +			buffer->element[element].length = length_here; +			buffer->element[element].eflags = +				SBAL_EFLAGS_MIDDLE_FRAG; +			length -= length_here; +			data += length_here; +			element++; +		}  	}  	if (buffer->element[element - 1].eflags) |