aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/netxen/netxen_nic_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/netxen/netxen_nic_init.c')
-rw-r--r--drivers/net/netxen/netxen_nic_init.c102
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
806static void
807netxen_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
846static void
847netxen_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
801static int 873static int
802netxen_alloc_rx_skb(struct netxen_adapter *adapter, 874netxen_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); 1031skip:
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