summaryrefslogtreecommitdiffstats
path: root/drivers/net/fjes
diff options
context:
space:
mode:
authorTaku Izumi <izumi.taku@jp.fujitsu.com>2015-08-21 04:29:27 -0400
committerDavid S. Miller <davem@davemloft.net>2015-08-24 17:06:35 -0400
commit265859309a761b4eec36620b324c9eb27a3cfee1 (patch)
tree9c730b9ae871fc56ec3e0ec418186c955336545a /drivers/net/fjes
parentac63b947085d8297bed10063cdf1ed6374d04b73 (diff)
fjes: NAPI polling function
This patch adds NAPI polling function and receive related work. Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/fjes')
-rw-r--r--drivers/net/fjes/fjes_hw.c40
-rw-r--r--drivers/net/fjes/fjes_hw.h5
-rw-r--r--drivers/net/fjes/fjes_main.c171
3 files changed, 214 insertions, 2 deletions
diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c
index 487dbc6b7c43..3c96d06d15cf 100644
--- a/drivers/net/fjes/fjes_hw.c
+++ b/drivers/net/fjes/fjes_hw.c
@@ -825,6 +825,46 @@ bool fjes_hw_check_vlan_id(struct epbuf_handler *epbh, u16 vlan_id)
825 return ret; 825 return ret;
826} 826}
827 827
828bool fjes_hw_epbuf_rx_is_empty(struct epbuf_handler *epbh)
829{
830 union ep_buffer_info *info = epbh->info;
831
832 if (info->v1i.count_max == 0)
833 return true;
834
835 return EP_RING_EMPTY(info->v1i.head, info->v1i.tail,
836 info->v1i.count_max);
837}
838
839void *fjes_hw_epbuf_rx_curpkt_get_addr(struct epbuf_handler *epbh,
840 size_t *psize)
841{
842 union ep_buffer_info *info = epbh->info;
843 struct esmem_frame *ring_frame;
844 void *frame;
845
846 ring_frame = (struct esmem_frame *)&(epbh->ring[EP_RING_INDEX
847 (info->v1i.head,
848 info->v1i.count_max) *
849 info->v1i.frame_max]);
850
851 *psize = (size_t)ring_frame->frame_size;
852
853 frame = ring_frame->frame_data;
854
855 return frame;
856}
857
858void fjes_hw_epbuf_rx_curpkt_drop(struct epbuf_handler *epbh)
859{
860 union ep_buffer_info *info = epbh->info;
861
862 if (fjes_hw_epbuf_rx_is_empty(epbh))
863 return;
864
865 EP_RING_INDEX_INC(epbh->info->v1i.head, info->v1i.count_max);
866}
867
828int fjes_hw_epbuf_tx_pkt_send(struct epbuf_handler *epbh, 868int fjes_hw_epbuf_tx_pkt_send(struct epbuf_handler *epbh,
829 void *frame, size_t size) 869 void *frame, size_t size)
830{ 870{
diff --git a/drivers/net/fjes/fjes_hw.h b/drivers/net/fjes/fjes_hw.h
index 07e122614a76..3511db2f7eb0 100644
--- a/drivers/net/fjes/fjes_hw.h
+++ b/drivers/net/fjes/fjes_hw.h
@@ -69,6 +69,8 @@ struct fjes_hw;
69 ((_num) = EP_RING_INDEX((_num) + 1, (_max))) 69 ((_num) = EP_RING_INDEX((_num) + 1, (_max)))
70#define EP_RING_FULL(_head, _tail, _max) \ 70#define EP_RING_FULL(_head, _tail, _max) \
71 (0 == EP_RING_INDEX(((_tail) - (_head)), (_max))) 71 (0 == EP_RING_INDEX(((_tail) - (_head)), (_max)))
72#define EP_RING_EMPTY(_head, _tail, _max) \
73 (1 == EP_RING_INDEX(((_tail) - (_head)), (_max)))
72 74
73#define FJES_MTU_TO_BUFFER_SIZE(mtu) \ 75#define FJES_MTU_TO_BUFFER_SIZE(mtu) \
74 (ETH_HLEN + VLAN_HLEN + (mtu) + ETH_FCS_LEN) 76 (ETH_HLEN + VLAN_HLEN + (mtu) + ETH_FCS_LEN)
@@ -320,6 +322,9 @@ int fjes_hw_epid_is_shared(struct fjes_device_shared_info *, int);
320bool fjes_hw_check_epbuf_version(struct epbuf_handler *, u32); 322bool fjes_hw_check_epbuf_version(struct epbuf_handler *, u32);
321bool fjes_hw_check_mtu(struct epbuf_handler *, u32); 323bool fjes_hw_check_mtu(struct epbuf_handler *, u32);
322bool fjes_hw_check_vlan_id(struct epbuf_handler *, u16); 324bool fjes_hw_check_vlan_id(struct epbuf_handler *, u16);
325bool fjes_hw_epbuf_rx_is_empty(struct epbuf_handler *);
326void *fjes_hw_epbuf_rx_curpkt_get_addr(struct epbuf_handler *, size_t *);
327void fjes_hw_epbuf_rx_curpkt_drop(struct epbuf_handler *);
323int fjes_hw_epbuf_tx_pkt_send(struct epbuf_handler *, void *, size_t); 328int fjes_hw_epbuf_tx_pkt_send(struct epbuf_handler *, void *, size_t);
324 329
325#endif /* FJES_HW_H_ */ 330#endif /* FJES_HW_H_ */
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index ac1e07636662..61949625176c 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -66,6 +66,9 @@ static int fjes_remove(struct platform_device *);
66static int fjes_sw_init(struct fjes_adapter *); 66static int fjes_sw_init(struct fjes_adapter *);
67static void fjes_netdev_setup(struct net_device *); 67static void fjes_netdev_setup(struct net_device *);
68 68
69static void fjes_rx_irq(struct fjes_adapter *, int);
70static int fjes_poll(struct napi_struct *, int);
71
69static const struct acpi_device_id fjes_acpi_ids[] = { 72static const struct acpi_device_id fjes_acpi_ids[] = {
70 {"PNP0C02", 0}, 73 {"PNP0C02", 0},
71 {"", 0}, 74 {"", 0},
@@ -235,6 +238,8 @@ static int fjes_open(struct net_device *netdev)
235 hw->txrx_stop_req_bit = 0; 238 hw->txrx_stop_req_bit = 0;
236 hw->epstop_req_bit = 0; 239 hw->epstop_req_bit = 0;
237 240
241 napi_enable(&adapter->napi);
242
238 fjes_hw_capture_interrupt_status(hw); 243 fjes_hw_capture_interrupt_status(hw);
239 244
240 result = fjes_request_irq(adapter); 245 result = fjes_request_irq(adapter);
@@ -250,6 +255,7 @@ static int fjes_open(struct net_device *netdev)
250 255
251err_req_irq: 256err_req_irq:
252 fjes_free_irq(adapter); 257 fjes_free_irq(adapter);
258 napi_disable(&adapter->napi);
253 259
254err_setup_res: 260err_setup_res:
255 fjes_free_resources(adapter); 261 fjes_free_resources(adapter);
@@ -268,6 +274,8 @@ static int fjes_close(struct net_device *netdev)
268 274
269 fjes_hw_raise_epstop(hw); 275 fjes_hw_raise_epstop(hw);
270 276
277 napi_disable(&adapter->napi);
278
271 for (epidx = 0; epidx < hw->max_epid; epidx++) { 279 for (epidx = 0; epidx < hw->max_epid; epidx++) {
272 if (epidx == hw->my_epid) 280 if (epidx == hw->my_epid)
273 continue; 281 continue;
@@ -701,14 +709,167 @@ static irqreturn_t fjes_intr(int irq, void *data)
701 709
702 icr = fjes_hw_capture_interrupt_status(hw); 710 icr = fjes_hw_capture_interrupt_status(hw);
703 711
704 if (icr & REG_IS_MASK_IS_ASSERT) 712 if (icr & REG_IS_MASK_IS_ASSERT) {
713 if (icr & REG_ICTL_MASK_RX_DATA)
714 fjes_rx_irq(adapter, icr & REG_IS_MASK_EPID);
715
705 ret = IRQ_HANDLED; 716 ret = IRQ_HANDLED;
706 else 717 } else {
707 ret = IRQ_NONE; 718 ret = IRQ_NONE;
719 }
708 720
709 return ret; 721 return ret;
710} 722}
711 723
724static int fjes_rxframe_search_exist(struct fjes_adapter *adapter,
725 int start_epid)
726{
727 struct fjes_hw *hw = &adapter->hw;
728 enum ep_partner_status pstatus;
729 int max_epid, cur_epid;
730 int i;
731
732 max_epid = hw->max_epid;
733 start_epid = (start_epid + 1 + max_epid) % max_epid;
734
735 for (i = 0; i < max_epid; i++) {
736 cur_epid = (start_epid + i) % max_epid;
737 if (cur_epid == hw->my_epid)
738 continue;
739
740 pstatus = fjes_hw_get_partner_ep_status(hw, cur_epid);
741 if (pstatus == EP_PARTNER_SHARED) {
742 if (!fjes_hw_epbuf_rx_is_empty(
743 &hw->ep_shm_info[cur_epid].rx))
744 return cur_epid;
745 }
746 }
747 return -1;
748}
749
750static void *fjes_rxframe_get(struct fjes_adapter *adapter, size_t *psize,
751 int *cur_epid)
752{
753 void *frame;
754
755 *cur_epid = fjes_rxframe_search_exist(adapter, *cur_epid);
756 if (*cur_epid < 0)
757 return NULL;
758
759 frame =
760 fjes_hw_epbuf_rx_curpkt_get_addr(
761 &adapter->hw.ep_shm_info[*cur_epid].rx, psize);
762
763 return frame;
764}
765
766static void fjes_rxframe_release(struct fjes_adapter *adapter, int cur_epid)
767{
768 fjes_hw_epbuf_rx_curpkt_drop(&adapter->hw.ep_shm_info[cur_epid].rx);
769}
770
771static void fjes_rx_irq(struct fjes_adapter *adapter, int src_epid)
772{
773 struct fjes_hw *hw = &adapter->hw;
774
775 fjes_hw_set_irqmask(hw, REG_ICTL_MASK_RX_DATA, true);
776
777 adapter->unset_rx_last = true;
778 napi_schedule(&adapter->napi);
779}
780
781static int fjes_poll(struct napi_struct *napi, int budget)
782{
783 struct fjes_adapter *adapter =
784 container_of(napi, struct fjes_adapter, napi);
785 struct net_device *netdev = napi->dev;
786 struct fjes_hw *hw = &adapter->hw;
787 struct sk_buff *skb;
788 int work_done = 0;
789 int cur_epid = 0;
790 int epidx;
791 size_t frame_len;
792 void *frame;
793
794 for (epidx = 0; epidx < hw->max_epid; epidx++) {
795 if (epidx == hw->my_epid)
796 continue;
797
798 adapter->hw.ep_shm_info[epidx].tx.info->v1i.rx_status |=
799 FJES_RX_POLL_WORK;
800 }
801
802 while (work_done < budget) {
803 prefetch(&adapter->hw);
804 frame = fjes_rxframe_get(adapter, &frame_len, &cur_epid);
805
806 if (frame) {
807 skb = napi_alloc_skb(napi, frame_len);
808 if (!skb) {
809 adapter->stats64.rx_dropped += 1;
810 hw->ep_shm_info[cur_epid].net_stats
811 .rx_dropped += 1;
812 adapter->stats64.rx_errors += 1;
813 hw->ep_shm_info[cur_epid].net_stats
814 .rx_errors += 1;
815 } else {
816 memcpy(skb_put(skb, frame_len),
817 frame, frame_len);
818 skb->protocol = eth_type_trans(skb, netdev);
819 skb->ip_summed = CHECKSUM_UNNECESSARY;
820
821 netif_receive_skb(skb);
822
823 work_done++;
824
825 adapter->stats64.rx_packets += 1;
826 hw->ep_shm_info[cur_epid].net_stats
827 .rx_packets += 1;
828 adapter->stats64.rx_bytes += frame_len;
829 hw->ep_shm_info[cur_epid].net_stats
830 .rx_bytes += frame_len;
831
832 if (is_multicast_ether_addr(
833 ((struct ethhdr *)frame)->h_dest)) {
834 adapter->stats64.multicast += 1;
835 hw->ep_shm_info[cur_epid].net_stats
836 .multicast += 1;
837 }
838 }
839
840 fjes_rxframe_release(adapter, cur_epid);
841 adapter->unset_rx_last = true;
842 } else {
843 break;
844 }
845 }
846
847 if (work_done < budget) {
848 napi_complete(napi);
849
850 if (adapter->unset_rx_last) {
851 adapter->rx_last_jiffies = jiffies;
852 adapter->unset_rx_last = false;
853 }
854
855 if (((long)jiffies - (long)adapter->rx_last_jiffies) < 3) {
856 napi_reschedule(napi);
857 } else {
858 for (epidx = 0; epidx < hw->max_epid; epidx++) {
859 if (epidx == hw->my_epid)
860 continue;
861 adapter->hw.ep_shm_info[epidx]
862 .tx.info->v1i.rx_status &=
863 ~FJES_RX_POLL_WORK;
864 }
865
866 fjes_hw_set_irqmask(hw, REG_ICTL_MASK_RX_DATA, false);
867 }
868 }
869
870 return work_done;
871}
872
712/* fjes_probe - Device Initialization Routine */ 873/* fjes_probe - Device Initialization Routine */
713static int fjes_probe(struct platform_device *plat_dev) 874static int fjes_probe(struct platform_device *plat_dev)
714{ 875{
@@ -797,6 +958,8 @@ static int fjes_remove(struct platform_device *plat_dev)
797 958
798 fjes_hw_exit(hw); 959 fjes_hw_exit(hw);
799 960
961 netif_napi_del(&adapter->napi);
962
800 free_netdev(netdev); 963 free_netdev(netdev);
801 964
802 return 0; 965 return 0;
@@ -804,6 +967,10 @@ static int fjes_remove(struct platform_device *plat_dev)
804 967
805static int fjes_sw_init(struct fjes_adapter *adapter) 968static int fjes_sw_init(struct fjes_adapter *adapter)
806{ 969{
970 struct net_device *netdev = adapter->netdev;
971
972 netif_napi_add(netdev, &adapter->napi, fjes_poll, 64);
973
807 return 0; 974 return 0;
808} 975}
809 976