aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ibmveth.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ibmveth.c')
-rw-r--r--drivers/net/ibmveth.c64
1 files changed, 42 insertions, 22 deletions
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index ba99af05bf62..d393f1e764ed 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -395,7 +395,7 @@ static inline struct sk_buff *ibmveth_rxq_get_buffer(struct ibmveth_adapter *ada
395} 395}
396 396
397/* recycle the current buffer on the rx queue */ 397/* recycle the current buffer on the rx queue */
398static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter) 398static int ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter)
399{ 399{
400 u32 q_index = adapter->rx_queue.index; 400 u32 q_index = adapter->rx_queue.index;
401 u64 correlator = adapter->rx_queue.queue_addr[q_index].correlator; 401 u64 correlator = adapter->rx_queue.queue_addr[q_index].correlator;
@@ -403,6 +403,7 @@ static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter)
403 unsigned int index = correlator & 0xffffffffUL; 403 unsigned int index = correlator & 0xffffffffUL;
404 union ibmveth_buf_desc desc; 404 union ibmveth_buf_desc desc;
405 unsigned long lpar_rc; 405 unsigned long lpar_rc;
406 int ret = 1;
406 407
407 BUG_ON(pool >= IBMVETH_NUM_BUFF_POOLS); 408 BUG_ON(pool >= IBMVETH_NUM_BUFF_POOLS);
408 BUG_ON(index >= adapter->rx_buff_pool[pool].size); 409 BUG_ON(index >= adapter->rx_buff_pool[pool].size);
@@ -410,7 +411,7 @@ static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter)
410 if (!adapter->rx_buff_pool[pool].active) { 411 if (!adapter->rx_buff_pool[pool].active) {
411 ibmveth_rxq_harvest_buffer(adapter); 412 ibmveth_rxq_harvest_buffer(adapter);
412 ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[pool]); 413 ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[pool]);
413 return; 414 goto out;
414 } 415 }
415 416
416 desc.fields.flags_len = IBMVETH_BUF_VALID | 417 desc.fields.flags_len = IBMVETH_BUF_VALID |
@@ -423,12 +424,16 @@ static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter)
423 netdev_dbg(adapter->netdev, "h_add_logical_lan_buffer failed " 424 netdev_dbg(adapter->netdev, "h_add_logical_lan_buffer failed "
424 "during recycle rc=%ld", lpar_rc); 425 "during recycle rc=%ld", lpar_rc);
425 ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator); 426 ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator);
427 ret = 0;
426 } 428 }
427 429
428 if (++adapter->rx_queue.index == adapter->rx_queue.num_slots) { 430 if (++adapter->rx_queue.index == adapter->rx_queue.num_slots) {
429 adapter->rx_queue.index = 0; 431 adapter->rx_queue.index = 0;
430 adapter->rx_queue.toggle = !adapter->rx_queue.toggle; 432 adapter->rx_queue.toggle = !adapter->rx_queue.toggle;
431 } 433 }
434
435out:
436 return ret;
432} 437}
433 438
434static void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter) 439static void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter)
@@ -631,8 +636,8 @@ static int ibmveth_open(struct net_device *netdev)
631 netdev_err(netdev, "unable to request irq 0x%x, rc %d\n", 636 netdev_err(netdev, "unable to request irq 0x%x, rc %d\n",
632 netdev->irq, rc); 637 netdev->irq, rc);
633 do { 638 do {
634 rc = h_free_logical_lan(adapter->vdev->unit_address); 639 lpar_rc = h_free_logical_lan(adapter->vdev->unit_address);
635 } while (H_IS_LONG_BUSY(rc) || (rc == H_BUSY)); 640 } while (H_IS_LONG_BUSY(lpar_rc) || (lpar_rc == H_BUSY));
636 641
637 goto err_out; 642 goto err_out;
638 } 643 }
@@ -752,7 +757,7 @@ static int ibmveth_set_csum_offload(struct net_device *dev, u32 data)
752 struct ibmveth_adapter *adapter = netdev_priv(dev); 757 struct ibmveth_adapter *adapter = netdev_priv(dev);
753 unsigned long set_attr, clr_attr, ret_attr; 758 unsigned long set_attr, clr_attr, ret_attr;
754 unsigned long set_attr6, clr_attr6; 759 unsigned long set_attr6, clr_attr6;
755 long ret, ret6; 760 long ret, ret4, ret6;
756 int rc1 = 0, rc2 = 0; 761 int rc1 = 0, rc2 = 0;
757 int restart = 0; 762 int restart = 0;
758 763
@@ -765,6 +770,8 @@ static int ibmveth_set_csum_offload(struct net_device *dev, u32 data)
765 770
766 set_attr = 0; 771 set_attr = 0;
767 clr_attr = 0; 772 clr_attr = 0;
773 set_attr6 = 0;
774 clr_attr6 = 0;
768 775
769 if (data) { 776 if (data) {
770 set_attr = IBMVETH_ILLAN_IPV4_TCP_CSUM; 777 set_attr = IBMVETH_ILLAN_IPV4_TCP_CSUM;
@@ -779,16 +786,20 @@ static int ibmveth_set_csum_offload(struct net_device *dev, u32 data)
779 if (ret == H_SUCCESS && !(ret_attr & IBMVETH_ILLAN_ACTIVE_TRUNK) && 786 if (ret == H_SUCCESS && !(ret_attr & IBMVETH_ILLAN_ACTIVE_TRUNK) &&
780 !(ret_attr & IBMVETH_ILLAN_TRUNK_PRI_MASK) && 787 !(ret_attr & IBMVETH_ILLAN_TRUNK_PRI_MASK) &&
781 (ret_attr & IBMVETH_ILLAN_PADDED_PKT_CSUM)) { 788 (ret_attr & IBMVETH_ILLAN_PADDED_PKT_CSUM)) {
782 ret = h_illan_attributes(adapter->vdev->unit_address, clr_attr, 789 ret4 = h_illan_attributes(adapter->vdev->unit_address, clr_attr,
783 set_attr, &ret_attr); 790 set_attr, &ret_attr);
784 791
785 if (ret != H_SUCCESS) { 792 if (ret4 != H_SUCCESS) {
786 netdev_err(dev, "unable to change IPv4 checksum " 793 netdev_err(dev, "unable to change IPv4 checksum "
787 "offload settings. %d rc=%ld\n", 794 "offload settings. %d rc=%ld\n",
788 data, ret); 795 data, ret4);
796
797 h_illan_attributes(adapter->vdev->unit_address,
798 set_attr, clr_attr, &ret_attr);
799
800 if (data == 1)
801 dev->features &= ~NETIF_F_IP_CSUM;
789 802
790 ret = h_illan_attributes(adapter->vdev->unit_address,
791 set_attr, clr_attr, &ret_attr);
792 } else { 803 } else {
793 adapter->fw_ipv4_csum_support = data; 804 adapter->fw_ipv4_csum_support = data;
794 } 805 }
@@ -799,15 +810,18 @@ static int ibmveth_set_csum_offload(struct net_device *dev, u32 data)
799 if (ret6 != H_SUCCESS) { 810 if (ret6 != H_SUCCESS) {
800 netdev_err(dev, "unable to change IPv6 checksum " 811 netdev_err(dev, "unable to change IPv6 checksum "
801 "offload settings. %d rc=%ld\n", 812 "offload settings. %d rc=%ld\n",
802 data, ret); 813 data, ret6);
814
815 h_illan_attributes(adapter->vdev->unit_address,
816 set_attr6, clr_attr6, &ret_attr);
817
818 if (data == 1)
819 dev->features &= ~NETIF_F_IPV6_CSUM;
803 820
804 ret = h_illan_attributes(adapter->vdev->unit_address,
805 set_attr6, clr_attr6,
806 &ret_attr);
807 } else 821 } else
808 adapter->fw_ipv6_csum_support = data; 822 adapter->fw_ipv6_csum_support = data;
809 823
810 if (ret != H_SUCCESS || ret6 != H_SUCCESS) 824 if (ret4 == H_SUCCESS || ret6 == H_SUCCESS)
811 adapter->rx_csum = data; 825 adapter->rx_csum = data;
812 else 826 else
813 rc1 = -EIO; 827 rc1 = -EIO;
@@ -925,6 +939,7 @@ static netdev_tx_t ibmveth_start_xmit(struct sk_buff *skb,
925 union ibmveth_buf_desc descs[6]; 939 union ibmveth_buf_desc descs[6];
926 int last, i; 940 int last, i;
927 int force_bounce = 0; 941 int force_bounce = 0;
942 dma_addr_t dma_addr;
928 943
929 /* 944 /*
930 * veth handles a maximum of 6 segments including the header, so 945 * veth handles a maximum of 6 segments including the header, so
@@ -989,17 +1004,16 @@ retry_bounce:
989 } 1004 }
990 1005
991 /* Map the header */ 1006 /* Map the header */
992 descs[0].fields.address = dma_map_single(&adapter->vdev->dev, skb->data, 1007 dma_addr = dma_map_single(&adapter->vdev->dev, skb->data,
993 skb_headlen(skb), 1008 skb_headlen(skb), DMA_TO_DEVICE);
994 DMA_TO_DEVICE); 1009 if (dma_mapping_error(&adapter->vdev->dev, dma_addr))
995 if (dma_mapping_error(&adapter->vdev->dev, descs[0].fields.address))
996 goto map_failed; 1010 goto map_failed;
997 1011
998 descs[0].fields.flags_len = desc_flags | skb_headlen(skb); 1012 descs[0].fields.flags_len = desc_flags | skb_headlen(skb);
1013 descs[0].fields.address = dma_addr;
999 1014
1000 /* Map the frags */ 1015 /* Map the frags */
1001 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 1016 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
1002 unsigned long dma_addr;
1003 skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 1017 skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
1004 1018
1005 dma_addr = dma_map_page(&adapter->vdev->dev, frag->page, 1019 dma_addr = dma_map_page(&adapter->vdev->dev, frag->page,
@@ -1021,7 +1035,12 @@ retry_bounce:
1021 netdev->stats.tx_bytes += skb->len; 1035 netdev->stats.tx_bytes += skb->len;
1022 } 1036 }
1023 1037
1024 for (i = 0; i < skb_shinfo(skb)->nr_frags + 1; i++) 1038 dma_unmap_single(&adapter->vdev->dev,
1039 descs[0].fields.address,
1040 descs[0].fields.flags_len & IBMVETH_BUF_LEN_MASK,
1041 DMA_TO_DEVICE);
1042
1043 for (i = 1; i < skb_shinfo(skb)->nr_frags + 1; i++)
1025 dma_unmap_page(&adapter->vdev->dev, descs[i].fields.address, 1044 dma_unmap_page(&adapter->vdev->dev, descs[i].fields.address,
1026 descs[i].fields.flags_len & IBMVETH_BUF_LEN_MASK, 1045 descs[i].fields.flags_len & IBMVETH_BUF_LEN_MASK,
1027 DMA_TO_DEVICE); 1046 DMA_TO_DEVICE);
@@ -1084,8 +1103,9 @@ restart_poll:
1084 if (rx_flush) 1103 if (rx_flush)
1085 ibmveth_flush_buffer(skb->data, 1104 ibmveth_flush_buffer(skb->data,
1086 length + offset); 1105 length + offset);
1106 if (!ibmveth_rxq_recycle_buffer(adapter))
1107 kfree_skb(skb);
1087 skb = new_skb; 1108 skb = new_skb;
1088 ibmveth_rxq_recycle_buffer(adapter);
1089 } else { 1109 } else {
1090 ibmveth_rxq_harvest_buffer(adapter); 1110 ibmveth_rxq_harvest_buffer(adapter);
1091 skb_reserve(skb, offset); 1111 skb_reserve(skb, offset);