forked from mirrors/linux
		
	qeth: enable scatter/gather in layer 2 mode
The patch enables NETIF_F_SG flag for OSA in layer 2 mode. It also adds performance accounting for fragmented sends, adds a conditional skb_linearize() attempt if the skb had too many fragments for QDIO SBAL, and fills netdevice->gso_* attributes. Signed-off-by: Eugene Crosser <Eugene.Crosser@ru.ibm.com> Signed-off-by: Ursula Braun <ubraun@linux.vnet.ibm.com> Reviewed-by: Lakhvich Dmitriy <ldmitriy@ru.ibm.com> Reviewed-by: Thomas Richter <tmricht@de.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									8bad55f8ce
								
							
						
					
					
						commit
						d52aec97e5
					
				
					 1 changed files with 25 additions and 1 deletions
				
			
		| 
						 | 
					@ -869,6 +869,7 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 | 
				
			||||||
	int data_offset = -1;
 | 
						int data_offset = -1;
 | 
				
			||||||
	int elements_needed = 0;
 | 
						int elements_needed = 0;
 | 
				
			||||||
	int hd_len = 0;
 | 
						int hd_len = 0;
 | 
				
			||||||
 | 
						int nr_frags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (card->qdio.do_prio_queueing || (cast_type &&
 | 
						if (card->qdio.do_prio_queueing || (cast_type &&
 | 
				
			||||||
					card->info.is_multicast_different))
 | 
										card->info.is_multicast_different))
 | 
				
			||||||
| 
						 | 
					@ -892,6 +893,17 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	netif_stop_queue(dev);
 | 
						netif_stop_queue(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* fix hardware limitation: as long as we do not have sbal
 | 
				
			||||||
 | 
						 * chaining we can not send long frag lists
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if ((card->info.type != QETH_CARD_TYPE_IQD) &&
 | 
				
			||||||
 | 
						    !qeth_get_elements_no(card, new_skb, 0)) {
 | 
				
			||||||
 | 
							if (skb_linearize(new_skb))
 | 
				
			||||||
 | 
								goto tx_drop;
 | 
				
			||||||
 | 
							if (card->options.performance_stats)
 | 
				
			||||||
 | 
								card->perf_stats.tx_lin++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (card->info.type == QETH_CARD_TYPE_OSN)
 | 
						if (card->info.type == QETH_CARD_TYPE_OSN)
 | 
				
			||||||
		hdr = (struct qeth_hdr *)skb->data;
 | 
							hdr = (struct qeth_hdr *)skb->data;
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
| 
						 | 
					@ -943,6 +955,14 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 | 
				
			||||||
	if (!rc) {
 | 
						if (!rc) {
 | 
				
			||||||
		card->stats.tx_packets++;
 | 
							card->stats.tx_packets++;
 | 
				
			||||||
		card->stats.tx_bytes += tx_bytes;
 | 
							card->stats.tx_bytes += tx_bytes;
 | 
				
			||||||
 | 
							if (card->options.performance_stats) {
 | 
				
			||||||
 | 
								nr_frags = skb_shinfo(new_skb)->nr_frags;
 | 
				
			||||||
 | 
								if (nr_frags) {
 | 
				
			||||||
 | 
									card->perf_stats.sg_skbs_sent++;
 | 
				
			||||||
 | 
									/* nr_frags + skb->data */
 | 
				
			||||||
 | 
									card->perf_stats.sg_frags_sent += nr_frags + 1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		if (new_skb != skb)
 | 
							if (new_skb != skb)
 | 
				
			||||||
			dev_kfree_skb_any(skb);
 | 
								dev_kfree_skb_any(skb);
 | 
				
			||||||
		rc = NETDEV_TX_OK;
 | 
							rc = NETDEV_TX_OK;
 | 
				
			||||||
| 
						 | 
					@ -1118,12 +1138,16 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
 | 
				
			||||||
		&qeth_l2_ethtool_ops : &qeth_l2_osn_ops;
 | 
							&qeth_l2_ethtool_ops : &qeth_l2_osn_ops;
 | 
				
			||||||
	card->dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
 | 
						card->dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
 | 
				
			||||||
	if (card->info.type == QETH_CARD_TYPE_OSD && !card->info.guestlan) {
 | 
						if (card->info.type == QETH_CARD_TYPE_OSD && !card->info.guestlan) {
 | 
				
			||||||
		card->dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
 | 
							card->dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
 | 
				
			||||||
 | 
										 NETIF_F_SG;
 | 
				
			||||||
		/* Turn on RX offloading per default */
 | 
							/* Turn on RX offloading per default */
 | 
				
			||||||
		card->dev->features |= NETIF_F_RXCSUM;
 | 
							card->dev->features |= NETIF_F_RXCSUM;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	card->info.broadcast_capable = 1;
 | 
						card->info.broadcast_capable = 1;
 | 
				
			||||||
	qeth_l2_request_initial_mac(card);
 | 
						qeth_l2_request_initial_mac(card);
 | 
				
			||||||
 | 
						card->dev->gso_max_size = (QETH_MAX_BUFFER_ELEMENTS(card) - 1) *
 | 
				
			||||||
 | 
									  PAGE_SIZE;
 | 
				
			||||||
 | 
						card->dev->gso_max_segs = (QETH_MAX_BUFFER_ELEMENTS(card) - 1);
 | 
				
			||||||
	SET_NETDEV_DEV(card->dev, &card->gdev->dev);
 | 
						SET_NETDEV_DEV(card->dev, &card->gdev->dev);
 | 
				
			||||||
	netif_napi_add(card->dev, &card->napi, qeth_l2_poll, QETH_NAPI_WEIGHT);
 | 
						netif_napi_add(card->dev, &card->napi, qeth_l2_poll, QETH_NAPI_WEIGHT);
 | 
				
			||||||
	netif_carrier_off(card->dev);
 | 
						netif_carrier_off(card->dev);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue