]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/net/netxen/netxen_nic_init.c
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[net-next-2.6.git] / drivers / net / netxen / netxen_nic_init.c
index 5d3343ef3d86312713481186b541656b1eba3470..e8bdbf9fefbb72e64883accec7569a1cebcc3cfc 100644 (file)
@@ -247,9 +247,14 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
                                rds_ring->skb_size =
                                        NX_CT_DEFAULT_RX_BUF_LEN;
                        } else {
-                               rds_ring->dma_size = RX_DMA_MAP_LEN;
+                               if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+                                       rds_ring->dma_size =
+                                               NX_P3_RX_BUF_MAX_LEN;
+                               else
+                                       rds_ring->dma_size =
+                                               NX_P2_RX_BUF_MAX_LEN;
                                rds_ring->skb_size =
-                                       MAX_RX_BUFFER_LENGTH;
+                                       rds_ring->dma_size + NET_IP_ALIGN;
                        }
                        break;
 
@@ -267,8 +272,8 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
 
                case RCV_RING_LRO:
                        rds_ring->num_desc = adapter->num_lro_rxd;
-                       rds_ring->dma_size = RX_LRO_DMA_MAP_LEN;
-                       rds_ring->skb_size = MAX_RX_LRO_BUFFER_LENGTH;
+                       rds_ring->dma_size = NX_RX_LRO_BUFFER_LENGTH;
+                       rds_ring->skb_size = rds_ring->dma_size + NET_IP_ALIGN;
                        break;
 
                }
@@ -880,22 +885,10 @@ netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname)
        return 0;
 }
 
-void netxen_request_firmware(struct netxen_adapter *adapter)
+static int
+netxen_p3_has_mn(struct netxen_adapter *adapter)
 {
        u32 capability, flashed_ver;
-       u8 fw_type;
-       struct pci_dev *pdev = adapter->pdev;
-       int rc = 0;
-
-       if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
-               fw_type = NX_P2_MN_ROMIMAGE;
-               goto request_fw;
-       } else {
-               fw_type = NX_P3_CT_ROMIMAGE;
-               goto request_fw;
-       }
-
-request_mn:
        capability = 0;
 
        netxen_rom_fast_read(adapter,
@@ -903,23 +896,35 @@ request_mn:
        flashed_ver = NETXEN_DECODE_VERSION(flashed_ver);
 
        if (flashed_ver >= NETXEN_VERSION_CODE(4, 0, 220)) {
+
                capability = NXRD32(adapter, NX_PEG_TUNE_CAPABILITY);
-               if (capability & NX_PEG_TUNE_MN_PRESENT) {
-                       fw_type = NX_P3_MN_ROMIMAGE;
-                       goto request_fw;
-               }
+               if (capability & NX_PEG_TUNE_MN_PRESENT)
+                       return 1;
        }
+       return 0;
+}
 
-       fw_type = NX_FLASH_ROMIMAGE;
-       adapter->fw = NULL;
-       goto done;
+void netxen_request_firmware(struct netxen_adapter *adapter)
+{
+       u8 fw_type;
+       struct pci_dev *pdev = adapter->pdev;
+       int rc = 0;
+
+       if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+               fw_type = NX_P2_MN_ROMIMAGE;
+               goto request_fw;
+       }
+
+       fw_type = netxen_p3_has_mn(adapter) ?
+               NX_P3_MN_ROMIMAGE : NX_P3_CT_ROMIMAGE;
 
 request_fw:
        rc = request_firmware(&adapter->fw, fw_name[fw_type], &pdev->dev);
        if (rc != 0) {
-               if (fw_type == NX_P3_CT_ROMIMAGE) {
+               if (fw_type == NX_P3_MN_ROMIMAGE) {
                        msleep(1);
-                       goto request_mn;
+                       fw_type = NX_P3_CT_ROMIMAGE;
+                       goto request_fw;
                }
 
                fw_type = NX_FLASH_ROMIMAGE;
@@ -931,9 +936,10 @@ request_fw:
        if (rc != 0) {
                release_firmware(adapter->fw);
 
-               if (fw_type == NX_P3_CT_ROMIMAGE) {
+               if (fw_type == NX_P3_MN_ROMIMAGE) {
                        msleep(1);
-                       goto request_mn;
+                       fw_type = NX_P3_CT_ROMIMAGE;
+                       goto request_fw;
                }
 
                fw_type = NX_FLASH_ROMIMAGE;
@@ -953,19 +959,20 @@ netxen_release_firmware(struct netxen_adapter *adapter)
                release_firmware(adapter->fw);
 }
 
-int netxen_initialize_adapter_offload(struct netxen_adapter *adapter)
+int netxen_init_dummy_dma(struct netxen_adapter *adapter)
 {
-       uint64_t addr;
-       uint32_t hi;
-       uint32_t lo;
+       u64 addr;
+       u32 hi, lo;
+
+       if (!NX_IS_REVISION_P2(adapter->ahw.revision_id))
+               return 0;
 
-       adapter->dummy_dma.addr =
-           pci_alloc_consistent(adapter->pdev,
+       adapter->dummy_dma.addr = pci_alloc_consistent(adapter->pdev,
                                 NETXEN_HOST_DUMMY_DMA_SIZE,
                                 &adapter->dummy_dma.phys_addr);
        if (adapter->dummy_dma.addr == NULL) {
-               printk("%s: ERROR: Could not allocate dummy DMA memory\n",
-                      __func__);
+               dev_err(&adapter->pdev->dev,
+                       "ERROR: Could not allocate dummy DMA memory\n");
                return -ENOMEM;
        }
 
@@ -976,29 +983,41 @@ int netxen_initialize_adapter_offload(struct netxen_adapter *adapter)
        NXWR32(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI, hi);
        NXWR32(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO, lo);
 
-       if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
-               uint32_t temp = 0;
-               NXWR32(adapter, CRB_HOST_DUMMY_BUF, temp);
-       }
-
        return 0;
 }
 
-void netxen_free_adapter_offload(struct netxen_adapter *adapter)
+/*
+ * NetXen DMA watchdog control:
+ *
+ *     Bit 0           : enabled => R/O: 1 watchdog active, 0 inactive
+ *     Bit 1           : disable_request => 1 req disable dma watchdog
+ *     Bit 2           : enable_request =>  1 req enable dma watchdog
+ *     Bit 3-31        : unused
+ */
+void netxen_free_dummy_dma(struct netxen_adapter *adapter)
 {
        int i = 100;
+       u32 ctrl;
+
+       if (!NX_IS_REVISION_P2(adapter->ahw.revision_id))
+               return;
 
        if (!adapter->dummy_dma.addr)
                return;
 
-       if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
-               do {
-                       if (dma_watchdog_shutdown_request(adapter) == 1)
-                               break;
+       ctrl = NXRD32(adapter, NETXEN_DMA_WATCHDOG_CTRL);
+       if ((ctrl & 0x1) != 0) {
+               NXWR32(adapter, NETXEN_DMA_WATCHDOG_CTRL, (ctrl | 0x2));
+
+               while ((ctrl & 0x1) != 0) {
+
                        msleep(50);
-                       if (dma_watchdog_shutdown_poll_result(adapter) == 1)
+
+                       ctrl = NXRD32(adapter, NETXEN_DMA_WATCHDOG_CTRL);
+
+                       if (--i == 0)
                                break;
-               } while (--i);
+               };
        }
 
        if (i) {
@@ -1007,10 +1026,8 @@ void netxen_free_adapter_offload(struct netxen_adapter *adapter)
                            adapter->dummy_dma.addr,
                            adapter->dummy_dma.phys_addr);
                adapter->dummy_dma.addr = NULL;
-       } else {
-               printk(KERN_ERR "%s: dma_watchdog_shutdown failed\n",
-                               adapter->netdev->name);
-       }
+       } else
+               dev_err(&adapter->pdev->dev, "dma_watchdog_shutdown failed\n");
 }
 
 int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val)
@@ -1083,10 +1100,6 @@ int netxen_init_firmware(struct netxen_adapter *adapter)
        NXWR32(adapter, CRB_MPORT_MODE, MPORT_MULTI_FUNCTION_MODE);
        NXWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK);
 
-       if (adapter->fw_version >= NETXEN_VERSION_CODE(4, 0, 222)) {
-               adapter->capabilities = NXRD32(adapter, CRB_FW_CAPABILITIES_1);
-       }
-
        return err;
 }
 
@@ -1222,20 +1235,31 @@ no_skb:
 
 static struct netxen_rx_buffer *
 netxen_process_rcv(struct netxen_adapter *adapter,
-               int ring, int index, int length, int cksum, int pkt_offset,
-               struct nx_host_sds_ring *sds_ring)
+               struct nx_host_sds_ring *sds_ring,
+               int ring, u64 sts_data0)
 {
        struct net_device *netdev = adapter->netdev;
        struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
        struct netxen_rx_buffer *buffer;
        struct sk_buff *skb;
-       struct nx_host_rds_ring *rds_ring = &recv_ctx->rds_rings[ring];
+       struct nx_host_rds_ring *rds_ring;
+       int index, length, cksum, pkt_offset;
 
-       if (unlikely(index > rds_ring->num_desc))
+       if (unlikely(ring >= adapter->max_rds_rings))
+               return NULL;
+
+       rds_ring = &recv_ctx->rds_rings[ring];
+
+       index = netxen_get_sts_refhandle(sts_data0);
+       if (unlikely(index >= rds_ring->num_desc))
                return NULL;
 
        buffer = &rds_ring->rx_buf_arr[index];
 
+       length = netxen_get_sts_totallength(sts_data0);
+       cksum  = netxen_get_sts_status(sts_data0);
+       pkt_offset = netxen_get_sts_pkt_offset(sts_data0);
+
        skb = netxen_process_rxbuf(adapter, rds_ring, index, cksum);
        if (!skb)
                return buffer;
@@ -1259,6 +1283,78 @@ netxen_process_rcv(struct netxen_adapter *adapter,
        return buffer;
 }
 
+#define TCP_HDR_SIZE            20
+#define TCP_TS_OPTION_SIZE      12
+#define TCP_TS_HDR_SIZE         (TCP_HDR_SIZE + TCP_TS_OPTION_SIZE)
+
+static struct netxen_rx_buffer *
+netxen_process_lro(struct netxen_adapter *adapter,
+               struct nx_host_sds_ring *sds_ring,
+               int ring, u64 sts_data0, u64 sts_data1)
+{
+       struct net_device *netdev = adapter->netdev;
+       struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
+       struct netxen_rx_buffer *buffer;
+       struct sk_buff *skb;
+       struct nx_host_rds_ring *rds_ring;
+       struct iphdr *iph;
+       struct tcphdr *th;
+       bool push, timestamp;
+       int l2_hdr_offset, l4_hdr_offset;
+       int index;
+       u16 lro_length, length, data_offset;
+       u32 seq_number;
+
+       if (unlikely(ring > adapter->max_rds_rings))
+               return NULL;
+
+       rds_ring = &recv_ctx->rds_rings[ring];
+
+       index = netxen_get_lro_sts_refhandle(sts_data0);
+       if (unlikely(index > rds_ring->num_desc))
+               return NULL;
+
+       buffer = &rds_ring->rx_buf_arr[index];
+
+       timestamp = netxen_get_lro_sts_timestamp(sts_data0);
+       lro_length = netxen_get_lro_sts_length(sts_data0);
+       l2_hdr_offset = netxen_get_lro_sts_l2_hdr_offset(sts_data0);
+       l4_hdr_offset = netxen_get_lro_sts_l4_hdr_offset(sts_data0);
+       push = netxen_get_lro_sts_push_flag(sts_data0);
+       seq_number = netxen_get_lro_sts_seq_number(sts_data1);
+
+       skb = netxen_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK);
+       if (!skb)
+               return buffer;
+
+       if (timestamp)
+               data_offset = l4_hdr_offset + TCP_TS_HDR_SIZE;
+       else
+               data_offset = l4_hdr_offset + TCP_HDR_SIZE;
+
+       skb_put(skb, lro_length + data_offset);
+
+       skb->truesize = (skb->len + sizeof(struct sk_buff) +
+                       ((unsigned long)skb->data - (unsigned long)skb->head));
+
+       skb_pull(skb, l2_hdr_offset);
+       skb->protocol = eth_type_trans(skb, netdev);
+
+       iph = (struct iphdr *)skb->data;
+       th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
+
+       length = (iph->ihl << 2) + (th->doff << 2) + lro_length;
+       iph->tot_len = htons(length);
+       iph->check = 0;
+       iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+       th->psh = push;
+       th->seq = htonl(seq_number);
+
+       netif_receive_skb(skb);
+
+       return buffer;
+}
+
 #define netxen_merge_rx_buffers(list, head) \
        do { list_splice_tail_init(list, head); } while (0);
 
@@ -1275,27 +1371,33 @@ netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max)
        u32 consumer = sds_ring->consumer;
 
        int count = 0;
-       u64 sts_data;
-       int opcode, ring, index, length, cksum, pkt_offset, desc_cnt;
+       u64 sts_data0, sts_data1;
+       int opcode, ring = 0, desc_cnt;
 
        while (count < max) {
                desc = &sds_ring->desc_head[consumer];
-               sts_data = le64_to_cpu(desc->status_desc_data[0]);
+               sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
 
-               if (!(sts_data & STATUS_OWNER_HOST))
+               if (!(sts_data0 & STATUS_OWNER_HOST))
                        break;
 
-               desc_cnt = netxen_get_sts_desc_cnt(sts_data);
-               ring   = netxen_get_sts_type(sts_data);
-
-               if (ring > RCV_RING_JUMBO)
-                       goto skip;
+               desc_cnt = netxen_get_sts_desc_cnt(sts_data0);
 
-               opcode = netxen_get_sts_opcode(sts_data);
+               opcode = netxen_get_sts_opcode(sts_data0);
 
                switch (opcode) {
                case NETXEN_NIC_RXPKT_DESC:
                case NETXEN_OLD_RXPKT_DESC:
+               case NETXEN_NIC_SYN_OFFLOAD:
+                       ring = netxen_get_sts_type(sts_data0);
+                       rxbuf = netxen_process_rcv(adapter, sds_ring,
+                                       ring, sts_data0);
+                       break;
+               case NETXEN_NIC_LRO_DESC:
+                       ring = netxen_get_lro_sts_type(sts_data0);
+                       sts_data1 = le64_to_cpu(desc->status_desc_data[1]);
+                       rxbuf = netxen_process_lro(adapter, sds_ring,
+                                       ring, sts_data0, sts_data1);
                        break;
                case NETXEN_NIC_RESPONSE_DESC:
                        netxen_handle_fw_message(desc_cnt, consumer, sds_ring);
@@ -1305,14 +1407,6 @@ netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max)
 
                WARN_ON(desc_cnt > 1);
 
-               index  = netxen_get_sts_refhandle(sts_data);
-               length = netxen_get_sts_totallength(sts_data);
-               cksum  = netxen_get_sts_status(sts_data);
-               pkt_offset = netxen_get_sts_pkt_offset(sts_data);
-
-               rxbuf = netxen_process_rcv(adapter, ring, index,
-                               length, cksum, pkt_offset, sds_ring);
-
                if (rxbuf)
                        list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]);
 
@@ -1468,7 +1562,7 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid,
                NXWR32(adapter, rds_ring->crb_rcv_producer,
                                (producer-1) & (rds_ring->num_desc-1));
 
-               if (adapter->fw_major < 4) {
+               if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
                        /*
                         * Write a doorbell msg to tell phanmon of change in
                         * receive ring producer