@@ -515,6 +515,208 @@ static int compare_versions(const char *a, const char *b)
515
515
return a_patch - b_patch ;
516
516
}
517
517
518
+ enum ef100_tlv_state_machine {
519
+ EF100_TLV_TYPE ,
520
+ EF100_TLV_TYPE_CONT ,
521
+ EF100_TLV_LENGTH ,
522
+ EF100_TLV_VALUE
523
+ };
524
+
525
+ struct ef100_tlv_state {
526
+ enum ef100_tlv_state_machine state ;
527
+ u64 value ;
528
+ u32 value_offset ;
529
+ u16 type ;
530
+ u8 len ;
531
+ };
532
+
533
+ static int ef100_tlv_feed (struct ef100_tlv_state * state , u8 byte )
534
+ {
535
+ switch (state -> state ) {
536
+ case EF100_TLV_TYPE :
537
+ state -> type = byte & 0x7f ;
538
+ state -> state = (byte & 0x80 ) ? EF100_TLV_TYPE_CONT
539
+ : EF100_TLV_LENGTH ;
540
+ /* Clear ready to read in a new entry */
541
+ state -> value = 0 ;
542
+ state -> value_offset = 0 ;
543
+ return 0 ;
544
+ case EF100_TLV_TYPE_CONT :
545
+ state -> type |= byte << 7 ;
546
+ state -> state = EF100_TLV_LENGTH ;
547
+ return 0 ;
548
+ case EF100_TLV_LENGTH :
549
+ state -> len = byte ;
550
+ /* We only handle TLVs that fit in a u64 */
551
+ if (state -> len > sizeof (state -> value ))
552
+ return - EOPNOTSUPP ;
553
+ /* len may be zero, implying a value of zero */
554
+ state -> state = state -> len ? EF100_TLV_VALUE : EF100_TLV_TYPE ;
555
+ return 0 ;
556
+ case EF100_TLV_VALUE :
557
+ state -> value |= ((u64 )byte ) << (state -> value_offset * 8 );
558
+ state -> value_offset ++ ;
559
+ if (state -> value_offset >= state -> len )
560
+ state -> state = EF100_TLV_TYPE ;
561
+ return 0 ;
562
+ default : /* state machine error, can't happen */
563
+ WARN_ON_ONCE (1 );
564
+ return - EIO ;
565
+ }
566
+ }
567
+
568
+ static int ef100_process_design_param (struct efx_nic * efx ,
569
+ const struct ef100_tlv_state * reader )
570
+ {
571
+ struct ef100_nic_data * nic_data = efx -> nic_data ;
572
+
573
+ switch (reader -> type ) {
574
+ case ESE_EF100_DP_GZ_PAD : /* padding, skip it */
575
+ return 0 ;
576
+ case ESE_EF100_DP_GZ_PARTIAL_TSTAMP_SUB_NANO_BITS :
577
+ /* Driver doesn't support timestamping yet, so we don't care */
578
+ return 0 ;
579
+ case ESE_EF100_DP_GZ_EVQ_UNSOL_CREDIT_SEQ_BITS :
580
+ /* Driver doesn't support unsolicited-event credits yet, so
581
+ * we don't care
582
+ */
583
+ return 0 ;
584
+ case ESE_EF100_DP_GZ_NMMU_GROUP_SIZE :
585
+ /* Driver doesn't manage the NMMU (so we don't care) */
586
+ return 0 ;
587
+ case ESE_EF100_DP_GZ_RX_L4_CSUM_PROTOCOLS :
588
+ /* Driver uses CHECKSUM_COMPLETE, so we don't care about
589
+ * protocol checksum validation
590
+ */
591
+ return 0 ;
592
+ case ESE_EF100_DP_GZ_TSO_MAX_HDR_LEN :
593
+ nic_data -> tso_max_hdr_len = min_t (u64 , reader -> value , 0xffff );
594
+ return 0 ;
595
+ case ESE_EF100_DP_GZ_TSO_MAX_HDR_NUM_SEGS :
596
+ /* We always put HDR_NUM_SEGS=1 in our TSO descriptors */
597
+ if (!reader -> value ) {
598
+ netif_err (efx , probe , efx -> net_dev ,
599
+ "TSO_MAX_HDR_NUM_SEGS < 1\n" );
600
+ return - EOPNOTSUPP ;
601
+ }
602
+ return 0 ;
603
+ case ESE_EF100_DP_GZ_RXQ_SIZE_GRANULARITY :
604
+ case ESE_EF100_DP_GZ_TXQ_SIZE_GRANULARITY :
605
+ /* Our TXQ and RXQ sizes are always power-of-two and thus divisible by
606
+ * EFX_MIN_DMAQ_SIZE, so we just need to check that
607
+ * EFX_MIN_DMAQ_SIZE is divisible by GRANULARITY.
608
+ * This is very unlikely to fail.
609
+ */
610
+ if (EFX_MIN_DMAQ_SIZE % reader -> value ) {
611
+ netif_err (efx , probe , efx -> net_dev ,
612
+ "%s size granularity is %llu, can't guarantee safety\n" ,
613
+ reader -> type == ESE_EF100_DP_GZ_RXQ_SIZE_GRANULARITY ? "RXQ" : "TXQ" ,
614
+ reader -> value );
615
+ return - EOPNOTSUPP ;
616
+ }
617
+ return 0 ;
618
+ case ESE_EF100_DP_GZ_TSO_MAX_PAYLOAD_LEN :
619
+ nic_data -> tso_max_payload_len = min_t (u64 , reader -> value , GSO_MAX_SIZE );
620
+ efx -> net_dev -> gso_max_size = nic_data -> tso_max_payload_len ;
621
+ return 0 ;
622
+ case ESE_EF100_DP_GZ_TSO_MAX_PAYLOAD_NUM_SEGS :
623
+ nic_data -> tso_max_payload_num_segs = min_t (u64 , reader -> value , 0xffff );
624
+ efx -> net_dev -> gso_max_segs = nic_data -> tso_max_payload_num_segs ;
625
+ return 0 ;
626
+ case ESE_EF100_DP_GZ_TSO_MAX_NUM_FRAMES :
627
+ nic_data -> tso_max_frames = min_t (u64 , reader -> value , 0xffff );
628
+ return 0 ;
629
+ case ESE_EF100_DP_GZ_COMPAT :
630
+ if (reader -> value ) {
631
+ netif_err (efx , probe , efx -> net_dev ,
632
+ "DP_COMPAT has unknown bits %#llx, driver not compatible with this hw\n" ,
633
+ reader -> value );
634
+ return - EOPNOTSUPP ;
635
+ }
636
+ return 0 ;
637
+ case ESE_EF100_DP_GZ_MEM2MEM_MAX_LEN :
638
+ /* Driver doesn't use mem2mem transfers */
639
+ return 0 ;
640
+ case ESE_EF100_DP_GZ_EVQ_TIMER_TICK_NANOS :
641
+ /* Driver doesn't currently use EVQ_TIMER */
642
+ return 0 ;
643
+ case ESE_EF100_DP_GZ_NMMU_PAGE_SIZES :
644
+ /* Driver doesn't manage the NMMU (so we don't care) */
645
+ return 0 ;
646
+ case ESE_EF100_DP_GZ_VI_STRIDES :
647
+ /* We never try to set the VI stride, and we don't rely on
648
+ * being able to find VIs past VI 0 until after we've learned
649
+ * the current stride from MC_CMD_GET_CAPABILITIES.
650
+ * So the value of this shouldn't matter.
651
+ */
652
+ if (reader -> value != ESE_EF100_DP_GZ_VI_STRIDES_DEFAULT )
653
+ netif_dbg (efx , probe , efx -> net_dev ,
654
+ "NIC has other than default VI_STRIDES (mask "
655
+ "%#llx), early probing might use wrong one\n" ,
656
+ reader -> value );
657
+ return 0 ;
658
+ case ESE_EF100_DP_GZ_RX_MAX_RUNT :
659
+ /* Driver doesn't look at L2_STATUS:LEN_ERR bit, so we don't
660
+ * care whether it indicates runt or overlength for any given
661
+ * packet, so we don't care about this parameter.
662
+ */
663
+ return 0 ;
664
+ default :
665
+ /* Host interface says "Drivers should ignore design parameters
666
+ * that they do not recognise."
667
+ */
668
+ netif_dbg (efx , probe , efx -> net_dev ,
669
+ "Ignoring unrecognised design parameter %u\n" ,
670
+ reader -> type );
671
+ return 0 ;
672
+ }
673
+ }
674
+
675
+ static int ef100_check_design_params (struct efx_nic * efx )
676
+ {
677
+ struct ef100_tlv_state reader = {};
678
+ u32 total_len , offset = 0 ;
679
+ efx_dword_t reg ;
680
+ int rc = 0 , i ;
681
+ u32 data ;
682
+
683
+ efx_readd (efx , & reg , ER_GZ_PARAMS_TLV_LEN );
684
+ total_len = EFX_DWORD_FIELD (reg , EFX_DWORD_0 );
685
+ netif_dbg (efx , probe , efx -> net_dev , "%u bytes of design parameters\n" ,
686
+ total_len );
687
+ while (offset < total_len ) {
688
+ efx_readd (efx , & reg , ER_GZ_PARAMS_TLV + offset );
689
+ data = EFX_DWORD_FIELD (reg , EFX_DWORD_0 );
690
+ for (i = 0 ; i < sizeof (data ); i ++ ) {
691
+ rc = ef100_tlv_feed (& reader , data );
692
+ /* Got a complete value? */
693
+ if (!rc && reader .state == EF100_TLV_TYPE )
694
+ rc = ef100_process_design_param (efx , & reader );
695
+ if (rc )
696
+ goto out ;
697
+ data >>= 8 ;
698
+ offset ++ ;
699
+ }
700
+ }
701
+ /* Check we didn't end halfway through a TLV entry, which could either
702
+ * mean that the TLV stream is truncated or just that it's corrupted
703
+ * and our state machine is out of sync.
704
+ */
705
+ if (reader .state != EF100_TLV_TYPE ) {
706
+ if (reader .state == EF100_TLV_TYPE_CONT )
707
+ netif_err (efx , probe , efx -> net_dev ,
708
+ "truncated design parameter (incomplete type %u)\n" ,
709
+ reader .type );
710
+ else
711
+ netif_err (efx , probe , efx -> net_dev ,
712
+ "truncated design parameter %u\n" ,
713
+ reader .type );
714
+ rc = - EIO ;
715
+ }
716
+ out :
717
+ return rc ;
718
+ }
719
+
518
720
/* NIC probe and remove
519
721
*/
520
722
static int ef100_probe_main (struct efx_nic * efx )
@@ -536,6 +738,20 @@ static int ef100_probe_main(struct efx_nic *efx)
536
738
net_dev -> features |= efx -> type -> offload_features ;
537
739
net_dev -> hw_features |= efx -> type -> offload_features ;
538
740
741
+ /* Populate design-parameter defaults */
742
+ nic_data -> tso_max_hdr_len = ESE_EF100_DP_GZ_TSO_MAX_HDR_LEN_DEFAULT ;
743
+ nic_data -> tso_max_frames = ESE_EF100_DP_GZ_TSO_MAX_NUM_FRAMES_DEFAULT ;
744
+ nic_data -> tso_max_payload_num_segs = ESE_EF100_DP_GZ_TSO_MAX_PAYLOAD_NUM_SEGS_DEFAULT ;
745
+ nic_data -> tso_max_payload_len = ESE_EF100_DP_GZ_TSO_MAX_PAYLOAD_LEN_DEFAULT ;
746
+ net_dev -> gso_max_segs = ESE_EF100_DP_GZ_TSO_MAX_HDR_NUM_SEGS_DEFAULT ;
747
+ /* Read design parameters */
748
+ rc = ef100_check_design_params (efx );
749
+ if (rc ) {
750
+ netif_err (efx , probe , efx -> net_dev ,
751
+ "Unsupported design parameters\n" );
752
+ goto fail ;
753
+ }
754
+
539
755
/* we assume later that we can copy from this buffer in dwords */
540
756
BUILD_BUG_ON (MCDI_CTL_SDU_LEN_MAX_V2 % 4 );
541
757
0 commit comments