@@ -515,6 +515,208 @@ static int compare_versions(const char *a, const char *b)
515515 return a_patch - b_patch ;
516516}
517517
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+
518720/* NIC probe and remove
519721 */
520722static int ef100_probe_main (struct efx_nic * efx )
@@ -536,6 +738,20 @@ static int ef100_probe_main(struct efx_nic *efx)
536738 net_dev -> features |= efx -> type -> offload_features ;
537739 net_dev -> hw_features |= efx -> type -> offload_features ;
538740
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+
539755 /* we assume later that we can copy from this buffer in dwords */
540756 BUILD_BUG_ON (MCDI_CTL_SDU_LEN_MAX_V2 % 4 );
541757
0 commit comments