diff options
Diffstat (limited to 'drivers/net/netxen/netxen_nic_init.c')
-rw-r--r-- | drivers/net/netxen/netxen_nic_init.c | 102 |
1 files changed, 96 insertions, 6 deletions
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 9991951e6e05..974783c45321 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c | |||
@@ -795,9 +795,81 @@ int netxen_init_firmware(struct netxen_adapter *adapter) | |||
795 | adapter->pci_write_normalize(adapter, | 795 | adapter->pci_write_normalize(adapter, |
796 | CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK); | 796 | CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK); |
797 | 797 | ||
798 | if (adapter->fw_version >= NETXEN_VERSION_CODE(4, 0, 222)) { | ||
799 | adapter->capabilities = netxen_nic_reg_read(adapter, | ||
800 | CRB_FW_CAPABILITIES_1); | ||
801 | } | ||
802 | |||
798 | return err; | 803 | return err; |
799 | } | 804 | } |
800 | 805 | ||
806 | static void | ||
807 | netxen_handle_linkevent(struct netxen_adapter *adapter, nx_fw_msg_t *msg) | ||
808 | { | ||
809 | u32 cable_OUI; | ||
810 | u16 cable_len; | ||
811 | u16 link_speed; | ||
812 | u8 link_status, module, duplex, autoneg; | ||
813 | struct net_device *netdev = adapter->netdev; | ||
814 | |||
815 | adapter->has_link_events = 1; | ||
816 | |||
817 | cable_OUI = msg->body[1] & 0xffffffff; | ||
818 | cable_len = (msg->body[1] >> 32) & 0xffff; | ||
819 | link_speed = (msg->body[1] >> 48) & 0xffff; | ||
820 | |||
821 | link_status = msg->body[2] & 0xff; | ||
822 | duplex = (msg->body[2] >> 16) & 0xff; | ||
823 | autoneg = (msg->body[2] >> 24) & 0xff; | ||
824 | |||
825 | module = (msg->body[2] >> 8) & 0xff; | ||
826 | if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE) { | ||
827 | printk(KERN_INFO "%s: unsupported cable: OUI 0x%x, length %d\n", | ||
828 | netdev->name, cable_OUI, cable_len); | ||
829 | } else if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN) { | ||
830 | printk(KERN_INFO "%s: unsupported cable length %d\n", | ||
831 | netdev->name, cable_len); | ||
832 | } | ||
833 | |||
834 | netxen_advert_link_change(adapter, link_status); | ||
835 | |||
836 | /* update link parameters */ | ||
837 | if (duplex == LINKEVENT_FULL_DUPLEX) | ||
838 | adapter->link_duplex = DUPLEX_FULL; | ||
839 | else | ||
840 | adapter->link_duplex = DUPLEX_HALF; | ||
841 | adapter->module_type = module; | ||
842 | adapter->link_autoneg = autoneg; | ||
843 | adapter->link_speed = link_speed; | ||
844 | } | ||
845 | |||
846 | static void | ||
847 | netxen_handle_fw_message(int desc_cnt, int index, | ||
848 | struct nx_host_sds_ring *sds_ring) | ||
849 | { | ||
850 | nx_fw_msg_t msg; | ||
851 | struct status_desc *desc; | ||
852 | int i = 0, opcode; | ||
853 | |||
854 | while (desc_cnt > 0 && i < 8) { | ||
855 | desc = &sds_ring->desc_head[index]; | ||
856 | msg.words[i++] = le64_to_cpu(desc->status_desc_data[0]); | ||
857 | msg.words[i++] = le64_to_cpu(desc->status_desc_data[1]); | ||
858 | |||
859 | index = get_next_index(index, sds_ring->num_desc); | ||
860 | desc_cnt--; | ||
861 | } | ||
862 | |||
863 | opcode = netxen_get_nic_msg_opcode(msg.body[0]); | ||
864 | switch (opcode) { | ||
865 | case NX_NIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE: | ||
866 | netxen_handle_linkevent(sds_ring->adapter, &msg); | ||
867 | break; | ||
868 | default: | ||
869 | break; | ||
870 | } | ||
871 | } | ||
872 | |||
801 | static int | 873 | static int |
802 | netxen_alloc_rx_skb(struct netxen_adapter *adapter, | 874 | netxen_alloc_rx_skb(struct netxen_adapter *adapter, |
803 | struct nx_host_rds_ring *rds_ring, | 875 | struct nx_host_rds_ring *rds_ring, |
@@ -916,21 +988,35 @@ netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max) | |||
916 | 988 | ||
917 | int count = 0; | 989 | int count = 0; |
918 | u64 sts_data; | 990 | u64 sts_data; |
919 | int opcode, ring, index, length, cksum, pkt_offset; | 991 | int opcode, ring, index, length, cksum, pkt_offset, desc_cnt; |
920 | 992 | ||
921 | while (count < max) { | 993 | while (count < max) { |
922 | desc = &sds_ring->desc_head[consumer]; | 994 | desc = &sds_ring->desc_head[consumer]; |
923 | sts_data = le64_to_cpu(desc->status_desc_data); | 995 | sts_data = le64_to_cpu(desc->status_desc_data[0]); |
924 | 996 | ||
925 | if (!(sts_data & STATUS_OWNER_HOST)) | 997 | if (!(sts_data & STATUS_OWNER_HOST)) |
926 | break; | 998 | break; |
927 | 999 | ||
1000 | desc_cnt = netxen_get_sts_desc_cnt(sts_data); | ||
928 | ring = netxen_get_sts_type(sts_data); | 1001 | ring = netxen_get_sts_type(sts_data); |
1002 | |||
929 | if (ring > RCV_RING_JUMBO) | 1003 | if (ring > RCV_RING_JUMBO) |
930 | continue; | 1004 | goto skip; |
931 | 1005 | ||
932 | opcode = netxen_get_sts_opcode(sts_data); | 1006 | opcode = netxen_get_sts_opcode(sts_data); |
933 | 1007 | ||
1008 | switch (opcode) { | ||
1009 | case NETXEN_NIC_RXPKT_DESC: | ||
1010 | case NETXEN_OLD_RXPKT_DESC: | ||
1011 | break; | ||
1012 | case NETXEN_NIC_RESPONSE_DESC: | ||
1013 | netxen_handle_fw_message(desc_cnt, consumer, sds_ring); | ||
1014 | default: | ||
1015 | goto skip; | ||
1016 | } | ||
1017 | |||
1018 | WARN_ON(desc_cnt > 1); | ||
1019 | |||
934 | index = netxen_get_sts_refhandle(sts_data); | 1020 | index = netxen_get_sts_refhandle(sts_data); |
935 | length = netxen_get_sts_totallength(sts_data); | 1021 | length = netxen_get_sts_totallength(sts_data); |
936 | cksum = netxen_get_sts_status(sts_data); | 1022 | cksum = netxen_get_sts_status(sts_data); |
@@ -942,9 +1028,13 @@ netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max) | |||
942 | if (rxbuf) | 1028 | if (rxbuf) |
943 | list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]); | 1029 | list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]); |
944 | 1030 | ||
945 | desc->status_desc_data = cpu_to_le64(STATUS_OWNER_PHANTOM); | 1031 | skip: |
946 | 1032 | for (; desc_cnt > 0; desc_cnt--) { | |
947 | consumer = get_next_index(consumer, sds_ring->num_desc); | 1033 | desc = &sds_ring->desc_head[consumer]; |
1034 | desc->status_desc_data[0] = | ||
1035 | cpu_to_le64(STATUS_OWNER_PHANTOM); | ||
1036 | consumer = get_next_index(consumer, sds_ring->num_desc); | ||
1037 | } | ||
948 | count++; | 1038 | count++; |
949 | } | 1039 | } |
950 | 1040 | ||