diff options
Diffstat (limited to 'drivers/net/netxen/netxen_nic_init.c')
-rw-r--r-- | drivers/net/netxen/netxen_nic_init.c | 367 |
1 files changed, 294 insertions, 73 deletions
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 0dca029bc3e5..290145ec08e7 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c | |||
@@ -1,25 +1,25 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2003 - 2006 NetXen, Inc. | 2 | * Copyright (C) 2003 - 2006 NetXen, Inc. |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
6 | * modify it under the terms of the GNU General Public License | 6 | * modify it under the terms of the GNU General Public License |
7 | * as published by the Free Software Foundation; either version 2 | 7 | * as published by the Free Software Foundation; either version 2 |
8 | * of the License, or (at your option) any later version. | 8 | * of the License, or (at your option) any later version. |
9 | * | 9 | * |
10 | * This program is distributed in the hope that it will be useful, but | 10 | * This program is distributed in the hope that it will be useful, but |
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | * GNU General Public License for more details. | 13 | * GNU General Public License for more details. |
14 | * | 14 | * |
15 | * You should have received a copy of the GNU General Public License | 15 | * You should have received a copy of the GNU General Public License |
16 | * along with this program; if not, write to the Free Software | 16 | * along with this program; if not, write to the Free Software |
17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, | 17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, |
18 | * MA 02111-1307, USA. | 18 | * MA 02111-1307, USA. |
19 | * | 19 | * |
20 | * The full GNU General Public License is included in this distribution | 20 | * The full GNU General Public License is included in this distribution |
21 | * in the file called LICENSE. | 21 | * in the file called LICENSE. |
22 | * | 22 | * |
23 | * Contact Information: | 23 | * Contact Information: |
24 | * info@netxen.com | 24 | * info@netxen.com |
25 | * NetXen, | 25 | * NetXen, |
@@ -137,6 +137,8 @@ int netxen_init_firmware(struct netxen_adapter *adapter) | |||
137 | return err; | 137 | return err; |
138 | } | 138 | } |
139 | /* Window 1 call */ | 139 | /* Window 1 call */ |
140 | writel(MPORT_SINGLE_FUNCTION_MODE, | ||
141 | NETXEN_CRB_NORMALIZE(adapter, CRB_MPORT_MODE)); | ||
140 | writel(PHAN_INITIALIZE_ACK, | 142 | writel(PHAN_INITIALIZE_ACK, |
141 | NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)); | 143 | NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)); |
142 | 144 | ||
@@ -184,15 +186,12 @@ void netxen_initialize_adapter_sw(struct netxen_adapter *adapter) | |||
184 | for (i = 0; i < num_rx_bufs; i++) { | 186 | for (i = 0; i < num_rx_bufs; i++) { |
185 | rx_buf->ref_handle = i; | 187 | rx_buf->ref_handle = i; |
186 | rx_buf->state = NETXEN_BUFFER_FREE; | 188 | rx_buf->state = NETXEN_BUFFER_FREE; |
187 | |||
188 | DPRINTK(INFO, "Rx buf:ctx%d i(%d) rx_buf:" | 189 | DPRINTK(INFO, "Rx buf:ctx%d i(%d) rx_buf:" |
189 | "%p\n", ctxid, i, rx_buf); | 190 | "%p\n", ctxid, i, rx_buf); |
190 | rx_buf++; | 191 | rx_buf++; |
191 | } | 192 | } |
192 | } | 193 | } |
193 | } | 194 | } |
194 | DPRINTK(INFO, "initialized buffers for %s and %s\n", | ||
195 | "adapter->free_cmd_buf_list", "adapter->free_rxbuf"); | ||
196 | } | 195 | } |
197 | 196 | ||
198 | void netxen_initialize_adapter_hw(struct netxen_adapter *adapter) | 197 | void netxen_initialize_adapter_hw(struct netxen_adapter *adapter) |
@@ -212,37 +211,36 @@ void netxen_initialize_adapter_hw(struct netxen_adapter *adapter) | |||
212 | 211 | ||
213 | void netxen_initialize_adapter_ops(struct netxen_adapter *adapter) | 212 | void netxen_initialize_adapter_ops(struct netxen_adapter *adapter) |
214 | { | 213 | { |
215 | struct netxen_drvops *ops = adapter->ops; | ||
216 | switch (adapter->ahw.board_type) { | 214 | switch (adapter->ahw.board_type) { |
217 | case NETXEN_NIC_GBE: | 215 | case NETXEN_NIC_GBE: |
218 | ops->enable_phy_interrupts = | 216 | adapter->enable_phy_interrupts = |
219 | netxen_niu_gbe_enable_phy_interrupts; | 217 | netxen_niu_gbe_enable_phy_interrupts; |
220 | ops->disable_phy_interrupts = | 218 | adapter->disable_phy_interrupts = |
221 | netxen_niu_gbe_disable_phy_interrupts; | 219 | netxen_niu_gbe_disable_phy_interrupts; |
222 | ops->handle_phy_intr = netxen_nic_gbe_handle_phy_intr; | 220 | adapter->handle_phy_intr = netxen_nic_gbe_handle_phy_intr; |
223 | ops->macaddr_set = netxen_niu_macaddr_set; | 221 | adapter->macaddr_set = netxen_niu_macaddr_set; |
224 | ops->set_mtu = netxen_nic_set_mtu_gb; | 222 | adapter->set_mtu = netxen_nic_set_mtu_gb; |
225 | ops->set_promisc = netxen_niu_set_promiscuous_mode; | 223 | adapter->set_promisc = netxen_niu_set_promiscuous_mode; |
226 | ops->unset_promisc = netxen_niu_set_promiscuous_mode; | 224 | adapter->unset_promisc = netxen_niu_set_promiscuous_mode; |
227 | ops->phy_read = netxen_niu_gbe_phy_read; | 225 | adapter->phy_read = netxen_niu_gbe_phy_read; |
228 | ops->phy_write = netxen_niu_gbe_phy_write; | 226 | adapter->phy_write = netxen_niu_gbe_phy_write; |
229 | ops->init_port = netxen_niu_gbe_init_port; | 227 | adapter->init_port = netxen_niu_gbe_init_port; |
230 | ops->init_niu = netxen_nic_init_niu_gb; | 228 | adapter->init_niu = netxen_nic_init_niu_gb; |
231 | ops->stop_port = netxen_niu_disable_gbe_port; | 229 | adapter->stop_port = netxen_niu_disable_gbe_port; |
232 | break; | 230 | break; |
233 | 231 | ||
234 | case NETXEN_NIC_XGBE: | 232 | case NETXEN_NIC_XGBE: |
235 | ops->enable_phy_interrupts = | 233 | adapter->enable_phy_interrupts = |
236 | netxen_niu_xgbe_enable_phy_interrupts; | 234 | netxen_niu_xgbe_enable_phy_interrupts; |
237 | ops->disable_phy_interrupts = | 235 | adapter->disable_phy_interrupts = |
238 | netxen_niu_xgbe_disable_phy_interrupts; | 236 | netxen_niu_xgbe_disable_phy_interrupts; |
239 | ops->handle_phy_intr = netxen_nic_xgbe_handle_phy_intr; | 237 | adapter->handle_phy_intr = netxen_nic_xgbe_handle_phy_intr; |
240 | ops->macaddr_set = netxen_niu_xg_macaddr_set; | 238 | adapter->macaddr_set = netxen_niu_xg_macaddr_set; |
241 | ops->set_mtu = netxen_nic_set_mtu_xgb; | 239 | adapter->set_mtu = netxen_nic_set_mtu_xgb; |
242 | ops->init_port = netxen_niu_xg_init_port; | 240 | adapter->init_port = netxen_niu_xg_init_port; |
243 | ops->set_promisc = netxen_niu_xg_set_promiscuous_mode; | 241 | adapter->set_promisc = netxen_niu_xg_set_promiscuous_mode; |
244 | ops->unset_promisc = netxen_niu_xg_set_promiscuous_mode; | 242 | adapter->unset_promisc = netxen_niu_xg_set_promiscuous_mode; |
245 | ops->stop_port = netxen_niu_disable_xg_port; | 243 | adapter->stop_port = netxen_niu_disable_xg_port; |
246 | break; | 244 | break; |
247 | 245 | ||
248 | default: | 246 | default: |
@@ -383,8 +381,8 @@ int netxen_rom_wip_poll(struct netxen_adapter *adapter) | |||
383 | return 0; | 381 | return 0; |
384 | } | 382 | } |
385 | 383 | ||
386 | static inline int do_rom_fast_write(struct netxen_adapter *adapter, | 384 | static inline int do_rom_fast_write(struct netxen_adapter *adapter, int addr, |
387 | int addr, int data) | 385 | int data) |
388 | { | 386 | { |
389 | if (netxen_rom_wren(adapter)) { | 387 | if (netxen_rom_wren(adapter)) { |
390 | return -1; | 388 | return -1; |
@@ -622,6 +620,43 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) | |||
622 | return 0; | 620 | return 0; |
623 | } | 621 | } |
624 | 622 | ||
623 | int netxen_initialize_adapter_offload(struct netxen_adapter *adapter) | ||
624 | { | ||
625 | uint64_t addr; | ||
626 | uint32_t hi; | ||
627 | uint32_t lo; | ||
628 | |||
629 | adapter->dummy_dma.addr = | ||
630 | pci_alloc_consistent(adapter->ahw.pdev, | ||
631 | NETXEN_HOST_DUMMY_DMA_SIZE, | ||
632 | &adapter->dummy_dma.phys_addr); | ||
633 | if (adapter->dummy_dma.addr == NULL) { | ||
634 | printk("%s: ERROR: Could not allocate dummy DMA memory\n", | ||
635 | __FUNCTION__); | ||
636 | return -ENOMEM; | ||
637 | } | ||
638 | |||
639 | addr = (uint64_t) adapter->dummy_dma.phys_addr; | ||
640 | hi = (addr >> 32) & 0xffffffff; | ||
641 | lo = addr & 0xffffffff; | ||
642 | |||
643 | writel(hi, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI)); | ||
644 | writel(lo, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO)); | ||
645 | |||
646 | return 0; | ||
647 | } | ||
648 | |||
649 | void netxen_free_adapter_offload(struct netxen_adapter *adapter) | ||
650 | { | ||
651 | if (adapter->dummy_dma.addr) { | ||
652 | pci_free_consistent(adapter->ahw.pdev, | ||
653 | NETXEN_HOST_DUMMY_DMA_SIZE, | ||
654 | adapter->dummy_dma.addr, | ||
655 | adapter->dummy_dma.phys_addr); | ||
656 | adapter->dummy_dma.addr = NULL; | ||
657 | } | ||
658 | } | ||
659 | |||
625 | void netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val) | 660 | void netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val) |
626 | { | 661 | { |
627 | u32 val = 0; | 662 | u32 val = 0; |
@@ -656,7 +691,8 @@ int netxen_nic_rx_has_work(struct netxen_adapter *adapter) | |||
656 | desc_head = recv_ctx->rcv_status_desc_head; | 691 | desc_head = recv_ctx->rcv_status_desc_head; |
657 | desc = &desc_head[consumer]; | 692 | desc = &desc_head[consumer]; |
658 | 693 | ||
659 | if (((le16_to_cpu(desc->owner)) & STATUS_OWNER_HOST)) | 694 | if (((le16_to_cpu(netxen_get_sts_owner(desc))) |
695 | & STATUS_OWNER_HOST)) | ||
660 | return 1; | 696 | return 1; |
661 | } | 697 | } |
662 | 698 | ||
@@ -710,12 +746,13 @@ static inline int netxen_nic_check_temp(struct netxen_adapter *adapter) | |||
710 | return rv; | 746 | return rv; |
711 | } | 747 | } |
712 | 748 | ||
713 | void netxen_watchdog_task(unsigned long v) | 749 | void netxen_watchdog_task(struct work_struct *work) |
714 | { | 750 | { |
715 | int port_num; | 751 | int port_num; |
716 | struct netxen_port *port; | 752 | struct netxen_port *port; |
717 | struct net_device *netdev; | 753 | struct net_device *netdev; |
718 | struct netxen_adapter *adapter = (struct netxen_adapter *)v; | 754 | struct netxen_adapter *adapter = |
755 | container_of(work, struct netxen_adapter, watchdog_task); | ||
719 | 756 | ||
720 | if (netxen_nic_check_temp(adapter)) | 757 | if (netxen_nic_check_temp(adapter)) |
721 | return; | 758 | return; |
@@ -734,8 +771,8 @@ void netxen_watchdog_task(unsigned long v) | |||
734 | netif_wake_queue(netdev); | 771 | netif_wake_queue(netdev); |
735 | } | 772 | } |
736 | 773 | ||
737 | if (adapter->ops->handle_phy_intr) | 774 | if (adapter->handle_phy_intr) |
738 | adapter->ops->handle_phy_intr(adapter); | 775 | adapter->handle_phy_intr(adapter); |
739 | mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); | 776 | mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); |
740 | } | 777 | } |
741 | 778 | ||
@@ -748,19 +785,19 @@ void | |||
748 | netxen_process_rcv(struct netxen_adapter *adapter, int ctxid, | 785 | netxen_process_rcv(struct netxen_adapter *adapter, int ctxid, |
749 | struct status_desc *desc) | 786 | struct status_desc *desc) |
750 | { | 787 | { |
751 | struct netxen_port *port = adapter->port[STATUS_DESC_PORT(desc)]; | 788 | struct netxen_port *port = adapter->port[netxen_get_sts_port(desc)]; |
752 | struct pci_dev *pdev = port->pdev; | 789 | struct pci_dev *pdev = port->pdev; |
753 | struct net_device *netdev = port->netdev; | 790 | struct net_device *netdev = port->netdev; |
754 | int index = le16_to_cpu(desc->reference_handle); | 791 | int index = le16_to_cpu(netxen_get_sts_refhandle(desc)); |
755 | struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctxid]); | 792 | struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctxid]); |
756 | struct netxen_rx_buffer *buffer; | 793 | struct netxen_rx_buffer *buffer; |
757 | struct sk_buff *skb; | 794 | struct sk_buff *skb; |
758 | u32 length = le16_to_cpu(desc->total_length); | 795 | u32 length = le16_to_cpu(netxen_get_sts_totallength(desc)); |
759 | u32 desc_ctx; | 796 | u32 desc_ctx; |
760 | struct netxen_rcv_desc_ctx *rcv_desc; | 797 | struct netxen_rcv_desc_ctx *rcv_desc; |
761 | int ret; | 798 | int ret; |
762 | 799 | ||
763 | desc_ctx = STATUS_DESC_TYPE(desc); | 800 | desc_ctx = netxen_get_sts_type(desc); |
764 | if (unlikely(desc_ctx >= NUM_RCV_DESC_RINGS)) { | 801 | if (unlikely(desc_ctx >= NUM_RCV_DESC_RINGS)) { |
765 | printk("%s: %s Bad Rcv descriptor ring\n", | 802 | printk("%s: %s Bad Rcv descriptor ring\n", |
766 | netxen_nic_driver_name, netdev->name); | 803 | netxen_nic_driver_name, netdev->name); |
@@ -768,20 +805,49 @@ netxen_process_rcv(struct netxen_adapter *adapter, int ctxid, | |||
768 | } | 805 | } |
769 | 806 | ||
770 | rcv_desc = &recv_ctx->rcv_desc[desc_ctx]; | 807 | rcv_desc = &recv_ctx->rcv_desc[desc_ctx]; |
808 | if (unlikely(index > rcv_desc->max_rx_desc_count)) { | ||
809 | DPRINTK(ERR, "Got a buffer index:%x Max is %x\n", | ||
810 | index, rcv_desc->max_rx_desc_count); | ||
811 | return; | ||
812 | } | ||
771 | buffer = &rcv_desc->rx_buf_arr[index]; | 813 | buffer = &rcv_desc->rx_buf_arr[index]; |
814 | if (desc_ctx == RCV_DESC_LRO_CTXID) { | ||
815 | buffer->lro_current_frags++; | ||
816 | if (netxen_get_sts_desc_lro_last_frag(desc)) { | ||
817 | buffer->lro_expected_frags = | ||
818 | netxen_get_sts_desc_lro_cnt(desc); | ||
819 | buffer->lro_length = length; | ||
820 | } | ||
821 | if (buffer->lro_current_frags != buffer->lro_expected_frags) { | ||
822 | if (buffer->lro_expected_frags != 0) { | ||
823 | printk("LRO: (refhandle:%x) recv frag." | ||
824 | "wait for last. flags: %x expected:%d" | ||
825 | "have:%d\n", index, | ||
826 | netxen_get_sts_desc_lro_last_frag(desc), | ||
827 | buffer->lro_expected_frags, | ||
828 | buffer->lro_current_frags); | ||
829 | } | ||
830 | return; | ||
831 | } | ||
832 | } | ||
772 | 833 | ||
773 | pci_unmap_single(pdev, buffer->dma, rcv_desc->dma_size, | 834 | pci_unmap_single(pdev, buffer->dma, rcv_desc->dma_size, |
774 | PCI_DMA_FROMDEVICE); | 835 | PCI_DMA_FROMDEVICE); |
775 | 836 | ||
776 | skb = (struct sk_buff *)buffer->skb; | 837 | skb = (struct sk_buff *)buffer->skb; |
777 | 838 | ||
778 | if (likely(STATUS_DESC_STATUS(desc) == STATUS_CKSUM_OK)) { | 839 | if (likely(netxen_get_sts_status(desc) == STATUS_CKSUM_OK)) { |
779 | port->stats.csummed++; | 840 | port->stats.csummed++; |
780 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 841 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
781 | } else | 842 | } |
782 | skb->ip_summed = CHECKSUM_NONE; | ||
783 | skb->dev = netdev; | 843 | skb->dev = netdev; |
784 | skb_put(skb, length); | 844 | if (desc_ctx == RCV_DESC_LRO_CTXID) { |
845 | /* True length was only available on the last pkt */ | ||
846 | skb_put(skb, buffer->lro_length); | ||
847 | } else { | ||
848 | skb_put(skb, length); | ||
849 | } | ||
850 | |||
785 | skb->protocol = eth_type_trans(skb, netdev); | 851 | skb->protocol = eth_type_trans(skb, netdev); |
786 | 852 | ||
787 | ret = netif_receive_skb(skb); | 853 | ret = netif_receive_skb(skb); |
@@ -827,6 +893,8 @@ netxen_process_rcv(struct netxen_adapter *adapter, int ctxid, | |||
827 | adapter->stats.post_called++; | 893 | adapter->stats.post_called++; |
828 | buffer->skb = NULL; | 894 | buffer->skb = NULL; |
829 | buffer->state = NETXEN_BUFFER_FREE; | 895 | buffer->state = NETXEN_BUFFER_FREE; |
896 | buffer->lro_current_frags = 0; | ||
897 | buffer->lro_expected_frags = 0; | ||
830 | 898 | ||
831 | port->stats.no_rcv++; | 899 | port->stats.no_rcv++; |
832 | port->stats.rxbytes += length; | 900 | port->stats.rxbytes += length; |
@@ -839,6 +907,7 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max) | |||
839 | struct status_desc *desc_head = recv_ctx->rcv_status_desc_head; | 907 | struct status_desc *desc_head = recv_ctx->rcv_status_desc_head; |
840 | struct status_desc *desc; /* used to read status desc here */ | 908 | struct status_desc *desc; /* used to read status desc here */ |
841 | u32 consumer = recv_ctx->status_rx_consumer; | 909 | u32 consumer = recv_ctx->status_rx_consumer; |
910 | u32 producer = 0; | ||
842 | int count = 0, ring; | 911 | int count = 0, ring; |
843 | 912 | ||
844 | DPRINTK(INFO, "procesing receive\n"); | 913 | DPRINTK(INFO, "procesing receive\n"); |
@@ -850,18 +919,22 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max) | |||
850 | */ | 919 | */ |
851 | while (count < max) { | 920 | while (count < max) { |
852 | desc = &desc_head[consumer]; | 921 | desc = &desc_head[consumer]; |
853 | if (!((le16_to_cpu(desc->owner)) & STATUS_OWNER_HOST)) { | 922 | if (! |
854 | DPRINTK(ERR, "desc %p ownedby %x\n", desc, desc->owner); | 923 | (le16_to_cpu(netxen_get_sts_owner(desc)) & |
924 | STATUS_OWNER_HOST)) { | ||
925 | DPRINTK(ERR, "desc %p ownedby %x\n", desc, | ||
926 | netxen_get_sts_owner(desc)); | ||
855 | break; | 927 | break; |
856 | } | 928 | } |
857 | netxen_process_rcv(adapter, ctxid, desc); | 929 | netxen_process_rcv(adapter, ctxid, desc); |
858 | desc->owner = STATUS_OWNER_PHANTOM; | 930 | netxen_clear_sts_owner(desc); |
931 | netxen_set_sts_owner(desc, STATUS_OWNER_PHANTOM); | ||
859 | consumer = (consumer + 1) & (adapter->max_rx_desc_count - 1); | 932 | consumer = (consumer + 1) & (adapter->max_rx_desc_count - 1); |
860 | count++; | 933 | count++; |
861 | } | 934 | } |
862 | if (count) { | 935 | if (count) { |
863 | for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) { | 936 | for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) { |
864 | netxen_post_rx_buffers(adapter, ctxid, ring); | 937 | netxen_post_rx_buffers_nodb(adapter, ctxid, ring); |
865 | } | 938 | } |
866 | } | 939 | } |
867 | 940 | ||
@@ -869,6 +942,7 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max) | |||
869 | if (count) { | 942 | if (count) { |
870 | adapter->stats.process_rcv++; | 943 | adapter->stats.process_rcv++; |
871 | recv_ctx->status_rx_consumer = consumer; | 944 | recv_ctx->status_rx_consumer = consumer; |
945 | recv_ctx->status_rx_producer = producer; | ||
872 | 946 | ||
873 | /* Window = 1 */ | 947 | /* Window = 1 */ |
874 | writel(consumer, | 948 | writel(consumer, |
@@ -881,12 +955,13 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max) | |||
881 | } | 955 | } |
882 | 956 | ||
883 | /* Process Command status ring */ | 957 | /* Process Command status ring */ |
884 | void netxen_process_cmd_ring(unsigned long data) | 958 | int netxen_process_cmd_ring(unsigned long data) |
885 | { | 959 | { |
886 | u32 last_consumer; | 960 | u32 last_consumer; |
887 | u32 consumer; | 961 | u32 consumer; |
888 | struct netxen_adapter *adapter = (struct netxen_adapter *)data; | 962 | struct netxen_adapter *adapter = (struct netxen_adapter *)data; |
889 | int count = 0; | 963 | int count1 = 0; |
964 | int count2 = 0; | ||
890 | struct netxen_cmd_buffer *buffer; | 965 | struct netxen_cmd_buffer *buffer; |
891 | struct netxen_port *port; /* port #1 */ | 966 | struct netxen_port *port; /* port #1 */ |
892 | struct netxen_port *nport; | 967 | struct netxen_port *nport; |
@@ -895,6 +970,7 @@ void netxen_process_cmd_ring(unsigned long data) | |||
895 | u32 i; | 970 | u32 i; |
896 | struct sk_buff *skb = NULL; | 971 | struct sk_buff *skb = NULL; |
897 | int p; | 972 | int p; |
973 | int done; | ||
898 | 974 | ||
899 | spin_lock(&adapter->tx_lock); | 975 | spin_lock(&adapter->tx_lock); |
900 | last_consumer = adapter->last_cmd_consumer; | 976 | last_consumer = adapter->last_cmd_consumer; |
@@ -904,14 +980,13 @@ void netxen_process_cmd_ring(unsigned long data) | |||
904 | * number as part of the descriptor. This way we will be able to get | 980 | * number as part of the descriptor. This way we will be able to get |
905 | * the netdev which is associated with that device. | 981 | * the netdev which is associated with that device. |
906 | */ | 982 | */ |
907 | consumer = | ||
908 | readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_CONSUMER_OFFSET)); | ||
909 | 983 | ||
984 | consumer = *(adapter->cmd_consumer); | ||
910 | if (last_consumer == consumer) { /* Ring is empty */ | 985 | if (last_consumer == consumer) { /* Ring is empty */ |
911 | DPRINTK(INFO, "last_consumer %d == consumer %d\n", | 986 | DPRINTK(INFO, "last_consumer %d == consumer %d\n", |
912 | last_consumer, consumer); | 987 | last_consumer, consumer); |
913 | spin_unlock(&adapter->tx_lock); | 988 | spin_unlock(&adapter->tx_lock); |
914 | return; | 989 | return 1; |
915 | } | 990 | } |
916 | 991 | ||
917 | adapter->proc_cmd_buf_counter++; | 992 | adapter->proc_cmd_buf_counter++; |
@@ -922,7 +997,7 @@ void netxen_process_cmd_ring(unsigned long data) | |||
922 | */ | 997 | */ |
923 | spin_unlock(&adapter->tx_lock); | 998 | spin_unlock(&adapter->tx_lock); |
924 | 999 | ||
925 | while ((last_consumer != consumer) && (count < MAX_STATUS_HANDLE)) { | 1000 | while ((last_consumer != consumer) && (count1 < MAX_STATUS_HANDLE)) { |
926 | buffer = &adapter->cmd_buf_arr[last_consumer]; | 1001 | buffer = &adapter->cmd_buf_arr[last_consumer]; |
927 | port = adapter->port[buffer->port]; | 1002 | port = adapter->port[buffer->port]; |
928 | pdev = port->pdev; | 1003 | pdev = port->pdev; |
@@ -948,24 +1023,25 @@ void netxen_process_cmd_ring(unsigned long data) | |||
948 | && netif_carrier_ok(port->netdev)) | 1023 | && netif_carrier_ok(port->netdev)) |
949 | && ((jiffies - port->netdev->trans_start) > | 1024 | && ((jiffies - port->netdev->trans_start) > |
950 | port->netdev->watchdog_timeo)) { | 1025 | port->netdev->watchdog_timeo)) { |
951 | schedule_work(&port->adapter->tx_timeout_task); | 1026 | SCHEDULE_WORK(port->adapter->tx_timeout_task |
1027 | + port->portnum); | ||
952 | } | 1028 | } |
953 | 1029 | ||
954 | last_consumer = get_next_index(last_consumer, | 1030 | last_consumer = get_next_index(last_consumer, |
955 | adapter->max_tx_desc_count); | 1031 | adapter->max_tx_desc_count); |
956 | count++; | 1032 | count1++; |
957 | } | 1033 | } |
958 | adapter->stats.noxmitdone += count; | 1034 | adapter->stats.noxmitdone += count1; |
959 | 1035 | ||
960 | count = 0; | 1036 | count2 = 0; |
961 | spin_lock(&adapter->tx_lock); | 1037 | spin_lock(&adapter->tx_lock); |
962 | if ((--adapter->proc_cmd_buf_counter) == 0) { | 1038 | if ((--adapter->proc_cmd_buf_counter) == 0) { |
963 | adapter->last_cmd_consumer = last_consumer; | 1039 | adapter->last_cmd_consumer = last_consumer; |
964 | while ((adapter->last_cmd_consumer != consumer) | 1040 | while ((adapter->last_cmd_consumer != consumer) |
965 | && (count < MAX_STATUS_HANDLE)) { | 1041 | && (count2 < MAX_STATUS_HANDLE)) { |
966 | buffer = | 1042 | buffer = |
967 | &adapter->cmd_buf_arr[adapter->last_cmd_consumer]; | 1043 | &adapter->cmd_buf_arr[adapter->last_cmd_consumer]; |
968 | count++; | 1044 | count2++; |
969 | if (buffer->skb) | 1045 | if (buffer->skb) |
970 | break; | 1046 | break; |
971 | else | 1047 | else |
@@ -974,7 +1050,7 @@ void netxen_process_cmd_ring(unsigned long data) | |||
974 | adapter->max_tx_desc_count); | 1050 | adapter->max_tx_desc_count); |
975 | } | 1051 | } |
976 | } | 1052 | } |
977 | if (count) { | 1053 | if (count1 || count2) { |
978 | for (p = 0; p < adapter->ahw.max_ports; p++) { | 1054 | for (p = 0; p < adapter->ahw.max_ports; p++) { |
979 | nport = adapter->port[p]; | 1055 | nport = adapter->port[p]; |
980 | if (netif_queue_stopped(nport->netdev) | 1056 | if (netif_queue_stopped(nport->netdev) |
@@ -984,10 +1060,30 @@ void netxen_process_cmd_ring(unsigned long data) | |||
984 | } | 1060 | } |
985 | } | 1061 | } |
986 | } | 1062 | } |
1063 | /* | ||
1064 | * If everything is freed up to consumer then check if the ring is full | ||
1065 | * If the ring is full then check if more needs to be freed and | ||
1066 | * schedule the call back again. | ||
1067 | * | ||
1068 | * This happens when there are 2 CPUs. One could be freeing and the | ||
1069 | * other filling it. If the ring is full when we get out of here and | ||
1070 | * the card has already interrupted the host then the host can miss the | ||
1071 | * interrupt. | ||
1072 | * | ||
1073 | * There is still a possible race condition and the host could miss an | ||
1074 | * interrupt. The card has to take care of this. | ||
1075 | */ | ||
1076 | if (adapter->last_cmd_consumer == consumer && | ||
1077 | (((adapter->cmd_producer + 1) % | ||
1078 | adapter->max_tx_desc_count) == adapter->last_cmd_consumer)) { | ||
1079 | consumer = *(adapter->cmd_consumer); | ||
1080 | } | ||
1081 | done = (adapter->last_cmd_consumer == consumer); | ||
987 | 1082 | ||
988 | spin_unlock(&adapter->tx_lock); | 1083 | spin_unlock(&adapter->tx_lock); |
989 | DPRINTK(INFO, "last consumer is %d in %s\n", last_consumer, | 1084 | DPRINTK(INFO, "last consumer is %d in %s\n", last_consumer, |
990 | __FUNCTION__); | 1085 | __FUNCTION__); |
1086 | return (done); | ||
991 | } | 1087 | } |
992 | 1088 | ||
993 | /* | 1089 | /* |
@@ -999,17 +1095,16 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid) | |||
999 | struct sk_buff *skb; | 1095 | struct sk_buff *skb; |
1000 | struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctx]); | 1096 | struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctx]); |
1001 | struct netxen_rcv_desc_ctx *rcv_desc = NULL; | 1097 | struct netxen_rcv_desc_ctx *rcv_desc = NULL; |
1002 | struct netxen_recv_crb *crbarea = &recv_crb_registers[ctx]; | 1098 | uint producer; |
1003 | struct netxen_rcv_desc_crb *rcv_desc_crb = NULL; | ||
1004 | u32 producer; | ||
1005 | struct rcv_desc *pdesc; | 1099 | struct rcv_desc *pdesc; |
1006 | struct netxen_rx_buffer *buffer; | 1100 | struct netxen_rx_buffer *buffer; |
1007 | int count = 0; | 1101 | int count = 0; |
1008 | int index = 0; | 1102 | int index = 0; |
1103 | netxen_ctx_msg msg = 0; | ||
1104 | dma_addr_t dma; | ||
1009 | 1105 | ||
1010 | adapter->stats.post_called++; | 1106 | adapter->stats.post_called++; |
1011 | rcv_desc = &recv_ctx->rcv_desc[ringid]; | 1107 | rcv_desc = &recv_ctx->rcv_desc[ringid]; |
1012 | rcv_desc_crb = &crbarea->rcv_desc_crb[ringid]; | ||
1013 | 1108 | ||
1014 | producer = rcv_desc->producer; | 1109 | producer = rcv_desc->producer; |
1015 | index = rcv_desc->begin_alloc; | 1110 | index = rcv_desc->begin_alloc; |
@@ -1019,6 +1114,7 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid) | |||
1019 | skb = dev_alloc_skb(rcv_desc->skb_size); | 1114 | skb = dev_alloc_skb(rcv_desc->skb_size); |
1020 | if (unlikely(!skb)) { | 1115 | if (unlikely(!skb)) { |
1021 | /* | 1116 | /* |
1117 | * TODO | ||
1022 | * We need to schedule the posting of buffers to the pegs. | 1118 | * We need to schedule the posting of buffers to the pegs. |
1023 | */ | 1119 | */ |
1024 | rcv_desc->begin_alloc = index; | 1120 | rcv_desc->begin_alloc = index; |
@@ -1026,9 +1122,105 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid) | |||
1026 | " allocated only %d buffers\n", count); | 1122 | " allocated only %d buffers\n", count); |
1027 | break; | 1123 | break; |
1028 | } | 1124 | } |
1125 | |||
1029 | count++; /* now there should be no failure */ | 1126 | count++; /* now there should be no failure */ |
1030 | pdesc = &rcv_desc->desc_head[producer]; | 1127 | pdesc = &rcv_desc->desc_head[producer]; |
1031 | skb_reserve(skb, NET_IP_ALIGN); | 1128 | |
1129 | #if defined(XGB_DEBUG) | ||
1130 | *(unsigned long *)(skb->head) = 0xc0debabe; | ||
1131 | if (skb_is_nonlinear(skb)) { | ||
1132 | printk("Allocated SKB @%p is nonlinear\n"); | ||
1133 | } | ||
1134 | #endif | ||
1135 | skb_reserve(skb, 2); | ||
1136 | /* This will be setup when we receive the | ||
1137 | * buffer after it has been filled FSL TBD TBD | ||
1138 | * skb->dev = netdev; | ||
1139 | */ | ||
1140 | dma = pci_map_single(pdev, skb->data, rcv_desc->dma_size, | ||
1141 | PCI_DMA_FROMDEVICE); | ||
1142 | pdesc->addr_buffer = dma; | ||
1143 | buffer->skb = skb; | ||
1144 | buffer->state = NETXEN_BUFFER_BUSY; | ||
1145 | buffer->dma = dma; | ||
1146 | /* make a rcv descriptor */ | ||
1147 | pdesc->reference_handle = buffer->ref_handle; | ||
1148 | pdesc->buffer_length = rcv_desc->dma_size; | ||
1149 | DPRINTK(INFO, "done writing descripter\n"); | ||
1150 | producer = | ||
1151 | get_next_index(producer, rcv_desc->max_rx_desc_count); | ||
1152 | index = get_next_index(index, rcv_desc->max_rx_desc_count); | ||
1153 | buffer = &rcv_desc->rx_buf_arr[index]; | ||
1154 | } | ||
1155 | /* if we did allocate buffers, then write the count to Phantom */ | ||
1156 | if (count) { | ||
1157 | rcv_desc->begin_alloc = index; | ||
1158 | rcv_desc->rcv_pending += count; | ||
1159 | adapter->stats.lastposted = count; | ||
1160 | adapter->stats.posted += count; | ||
1161 | rcv_desc->producer = producer; | ||
1162 | if (rcv_desc->rcv_free >= 32) { | ||
1163 | rcv_desc->rcv_free = 0; | ||
1164 | /* Window = 1 */ | ||
1165 | writel((producer - 1) & | ||
1166 | (rcv_desc->max_rx_desc_count - 1), | ||
1167 | NETXEN_CRB_NORMALIZE(adapter, | ||
1168 | recv_crb_registers[0]. | ||
1169 | rcv_desc_crb[ringid]. | ||
1170 | crb_rcv_producer_offset)); | ||
1171 | /* | ||
1172 | * Write a doorbell msg to tell phanmon of change in | ||
1173 | * receive ring producer | ||
1174 | */ | ||
1175 | netxen_set_msg_peg_id(msg, NETXEN_RCV_PEG_DB_ID); | ||
1176 | netxen_set_msg_privid(msg); | ||
1177 | netxen_set_msg_count(msg, | ||
1178 | ((producer - | ||
1179 | 1) & (rcv_desc-> | ||
1180 | max_rx_desc_count - 1))); | ||
1181 | netxen_set_msg_ctxid(msg, 0); | ||
1182 | netxen_set_msg_opcode(msg, NETXEN_RCV_PRODUCER(ringid)); | ||
1183 | writel(msg, | ||
1184 | DB_NORMALIZE(adapter, | ||
1185 | NETXEN_RCV_PRODUCER_OFFSET)); | ||
1186 | } | ||
1187 | } | ||
1188 | } | ||
1189 | |||
1190 | void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, uint32_t ctx, | ||
1191 | uint32_t ringid) | ||
1192 | { | ||
1193 | struct pci_dev *pdev = adapter->ahw.pdev; | ||
1194 | struct sk_buff *skb; | ||
1195 | struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctx]); | ||
1196 | struct netxen_rcv_desc_ctx *rcv_desc = NULL; | ||
1197 | u32 producer; | ||
1198 | struct rcv_desc *pdesc; | ||
1199 | struct netxen_rx_buffer *buffer; | ||
1200 | int count = 0; | ||
1201 | int index = 0; | ||
1202 | |||
1203 | adapter->stats.post_called++; | ||
1204 | rcv_desc = &recv_ctx->rcv_desc[ringid]; | ||
1205 | |||
1206 | producer = rcv_desc->producer; | ||
1207 | index = rcv_desc->begin_alloc; | ||
1208 | buffer = &rcv_desc->rx_buf_arr[index]; | ||
1209 | /* We can start writing rx descriptors into the phantom memory. */ | ||
1210 | while (buffer->state == NETXEN_BUFFER_FREE) { | ||
1211 | skb = dev_alloc_skb(rcv_desc->skb_size); | ||
1212 | if (unlikely(!skb)) { | ||
1213 | /* | ||
1214 | * We need to schedule the posting of buffers to the pegs. | ||
1215 | */ | ||
1216 | rcv_desc->begin_alloc = index; | ||
1217 | DPRINTK(ERR, "netxen_post_rx_buffers_nodb: " | ||
1218 | " allocated only %d buffers\n", count); | ||
1219 | break; | ||
1220 | } | ||
1221 | count++; /* now there should be no failure */ | ||
1222 | pdesc = &rcv_desc->desc_head[producer]; | ||
1223 | skb_reserve(skb, 2); | ||
1032 | /* | 1224 | /* |
1033 | * This will be setup when we receive the | 1225 | * This will be setup when we receive the |
1034 | * buffer after it has been filled | 1226 | * buffer after it has been filled |
@@ -1039,6 +1231,7 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid) | |||
1039 | buffer->dma = pci_map_single(pdev, skb->data, | 1231 | buffer->dma = pci_map_single(pdev, skb->data, |
1040 | rcv_desc->dma_size, | 1232 | rcv_desc->dma_size, |
1041 | PCI_DMA_FROMDEVICE); | 1233 | PCI_DMA_FROMDEVICE); |
1234 | |||
1042 | /* make a rcv descriptor */ | 1235 | /* make a rcv descriptor */ |
1043 | pdesc->reference_handle = le16_to_cpu(buffer->ref_handle); | 1236 | pdesc->reference_handle = le16_to_cpu(buffer->ref_handle); |
1044 | pdesc->buffer_length = le16_to_cpu(rcv_desc->dma_size); | 1237 | pdesc->buffer_length = le16_to_cpu(rcv_desc->dma_size); |
@@ -1063,7 +1256,8 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid) | |||
1063 | writel((producer - 1) & | 1256 | writel((producer - 1) & |
1064 | (rcv_desc->max_rx_desc_count - 1), | 1257 | (rcv_desc->max_rx_desc_count - 1), |
1065 | NETXEN_CRB_NORMALIZE(adapter, | 1258 | NETXEN_CRB_NORMALIZE(adapter, |
1066 | rcv_desc_crb-> | 1259 | recv_crb_registers[0]. |
1260 | rcv_desc_crb[ringid]. | ||
1067 | crb_rcv_producer_offset)); | 1261 | crb_rcv_producer_offset)); |
1068 | wmb(); | 1262 | wmb(); |
1069 | } | 1263 | } |
@@ -1196,8 +1390,8 @@ netxen_nic_do_ioctl(struct netxen_adapter *adapter, void *u_data, | |||
1196 | 1390 | ||
1197 | switch (data.cmd) { | 1391 | switch (data.cmd) { |
1198 | case netxen_nic_cmd_pci_read: | 1392 | case netxen_nic_cmd_pci_read: |
1199 | if ((retval = netxen_nic_hw_read_wx(adapter, data.off, | 1393 | if ((retval = netxen_nic_hw_read_ioctl(adapter, data.off, |
1200 | &(data.u), data.size))) | 1394 | &(data.u), data.size))) |
1201 | goto error_out; | 1395 | goto error_out; |
1202 | if (copy_to_user | 1396 | if (copy_to_user |
1203 | ((void __user *)&(up_data->u), &(data.u), data.size)) { | 1397 | ((void __user *)&(up_data->u), &(data.u), data.size)) { |
@@ -1210,8 +1404,35 @@ netxen_nic_do_ioctl(struct netxen_adapter *adapter, void *u_data, | |||
1210 | break; | 1404 | break; |
1211 | 1405 | ||
1212 | case netxen_nic_cmd_pci_write: | 1406 | case netxen_nic_cmd_pci_write: |
1213 | data.rv = netxen_nic_hw_write_wx(adapter, data.off, &(data.u), | 1407 | if ((retval = netxen_nic_hw_write_ioctl(adapter, data.off, |
1214 | data.size); | 1408 | &(data.u), data.size))) |
1409 | goto error_out; | ||
1410 | data.rv = 0; | ||
1411 | break; | ||
1412 | |||
1413 | case netxen_nic_cmd_pci_mem_read: | ||
1414 | if (netxen_nic_pci_mem_read_ioctl(adapter, data.off, &(data.u), | ||
1415 | data.size)) { | ||
1416 | DPRINTK(ERR, "Failed to read the data.\n"); | ||
1417 | retval = -EFAULT; | ||
1418 | goto error_out; | ||
1419 | } | ||
1420 | if (copy_to_user | ||
1421 | ((void __user *)&(up_data->u), &(data.u), data.size)) { | ||
1422 | DPRINTK(ERR, "bad copy to userland: %d\n", | ||
1423 | (int)sizeof(data)); | ||
1424 | retval = -EFAULT; | ||
1425 | goto error_out; | ||
1426 | } | ||
1427 | data.rv = 0; | ||
1428 | break; | ||
1429 | |||
1430 | case netxen_nic_cmd_pci_mem_write: | ||
1431 | if ((retval = netxen_nic_pci_mem_write_ioctl(adapter, data.off, | ||
1432 | &(data.u), | ||
1433 | data.size))) | ||
1434 | goto error_out; | ||
1435 | data.rv = 0; | ||
1215 | break; | 1436 | break; |
1216 | 1437 | ||
1217 | case netxen_nic_cmd_pci_config_read: | 1438 | case netxen_nic_cmd_pci_config_read: |
@@ -1296,7 +1517,7 @@ netxen_nic_do_ioctl(struct netxen_adapter *adapter, void *u_data, | |||
1296 | retval = -EOPNOTSUPP; | 1517 | retval = -EOPNOTSUPP; |
1297 | goto error_out; | 1518 | goto error_out; |
1298 | } | 1519 | } |
1299 | put_user(data.rv, (u16 __user *) (&(up_data->rv))); | 1520 | put_user(data.rv, (&(up_data->rv))); |
1300 | DPRINTK(INFO, "done ioctl for %p well.\n", adapter); | 1521 | DPRINTK(INFO, "done ioctl for %p well.\n", adapter); |
1301 | 1522 | ||
1302 | error_out: | 1523 | error_out: |