Browse Source

[efi] Work around bugs in Emulex NII driver

Modified-by: Michael Brown <mcb30@ipxe.org>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Fabrice Bacchella 9 years ago
parent
commit
c0b61bad99
1 changed files with 71 additions and 15 deletions
  1. 71
    15
      src/drivers/net/efi/nii.c

+ 71
- 15
src/drivers/net/efi/nii.c View File

575
  * Initialise UNDI
575
  * Initialise UNDI
576
  *
576
  *
577
  * @v nii		NII NIC
577
  * @v nii		NII NIC
578
+ * @v flags		Flags
578
  * @ret rc		Return status code
579
  * @ret rc		Return status code
579
  */
580
  */
580
-static int nii_initialise ( struct nii_nic *nii ) {
581
+static int nii_initialise_flags ( struct nii_nic *nii, unsigned int flags ) {
581
 	PXE_CPB_INITIALIZE cpb;
582
 	PXE_CPB_INITIALIZE cpb;
582
 	PXE_DB_INITIALIZE db;
583
 	PXE_DB_INITIALIZE db;
583
 	unsigned int op;
584
 	unsigned int op;
600
 	memset ( &db, 0, sizeof ( db ) );
601
 	memset ( &db, 0, sizeof ( db ) );
601
 
602
 
602
 	/* Issue command */
603
 	/* Issue command */
603
-	op = NII_OP ( PXE_OPCODE_INITIALIZE,
604
-		      PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE );
604
+	op = NII_OP ( PXE_OPCODE_INITIALIZE, flags );
605
 	if ( ( stat = nii_issue_cpb_db ( nii, op, &cpb, sizeof ( cpb ),
605
 	if ( ( stat = nii_issue_cpb_db ( nii, op, &cpb, sizeof ( cpb ),
606
 					 &db, sizeof ( db ) ) ) < 0 ) {
606
 					 &db, sizeof ( db ) ) ) < 0 ) {
607
 		rc = -EIO_STAT ( stat );
607
 		rc = -EIO_STAT ( stat );
618
 	return rc;
618
 	return rc;
619
 }
619
 }
620
 
620
 
621
+/**
622
+ * Initialise UNDI
623
+ *
624
+ * @v nii		NII NIC
625
+ * @ret rc		Return status code
626
+ */
627
+static int nii_initialise ( struct nii_nic *nii ) {
628
+	unsigned int flags;
629
+
630
+	/* Initialise UNDI */
631
+	flags = PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE;
632
+	return nii_initialise_flags ( nii, flags );
633
+}
634
+
635
+/**
636
+ * Initialise UNDI and detect cable
637
+ *
638
+ * @v nii		NII NIC
639
+ * @ret rc		Return status code
640
+ */
641
+static int nii_initialise_and_detect ( struct nii_nic *nii ) {
642
+	unsigned int flags;
643
+
644
+	/* Initialise UNDI and detect cable.  This is required to work
645
+	 * around bugs in some Emulex NII drivers.
646
+	 */
647
+	flags = PXE_OPFLAGS_INITIALIZE_DETECT_CABLE;
648
+	return nii_initialise_flags ( nii, flags );
649
+}
650
+
621
 /**
651
 /**
622
  * Shut down UNDI
652
  * Shut down UNDI
623
  *
653
  *
650
 static int nii_get_station_address ( struct nii_nic *nii,
680
 static int nii_get_station_address ( struct nii_nic *nii,
651
 				     struct net_device *netdev ) {
681
 				     struct net_device *netdev ) {
652
 	PXE_DB_STATION_ADDRESS db;
682
 	PXE_DB_STATION_ADDRESS db;
683
+	unsigned int op;
653
 	int stat;
684
 	int stat;
654
 	int rc;
685
 	int rc;
655
 
686
 
658
 		goto err_initialise;
689
 		goto err_initialise;
659
 
690
 
660
 	/* Issue command */
691
 	/* Issue command */
661
-	if ( ( stat = nii_issue_db ( nii, PXE_OPCODE_STATION_ADDRESS, &db,
662
-				     sizeof ( db ) ) ) < 0 ) {
692
+	op = NII_OP ( PXE_OPCODE_STATION_ADDRESS,
693
+		      PXE_OPFLAGS_STATION_ADDRESS_READ );
694
+	if ( ( stat = nii_issue_db ( nii, op, &db, sizeof ( db ) ) ) < 0 ) {
663
 		rc = -EIO_STAT ( stat );
695
 		rc = -EIO_STAT ( stat );
664
 		DBGC ( nii, "NII %s could not get station address: %s\n",
696
 		DBGC ( nii, "NII %s could not get station address: %s\n",
665
 		       nii->dev.name, strerror ( rc ) );
697
 		       nii->dev.name, strerror ( rc ) );
689
  */
721
  */
690
 static int nii_set_station_address ( struct nii_nic *nii,
722
 static int nii_set_station_address ( struct nii_nic *nii,
691
 				     struct net_device *netdev ) {
723
 				     struct net_device *netdev ) {
724
+	uint32_t implementation = nii->undi->Implementation;
692
 	PXE_CPB_STATION_ADDRESS cpb;
725
 	PXE_CPB_STATION_ADDRESS cpb;
726
+	unsigned int op;
693
 	int stat;
727
 	int stat;
694
 	int rc;
728
 	int rc;
695
 
729
 
730
+	/* Fail if setting station address is unsupported */
731
+	if ( ! ( implementation & PXE_ROMID_IMP_STATION_ADDR_SETTABLE ) )
732
+		return -ENOTSUP;
733
+
696
 	/* Construct parameter block */
734
 	/* Construct parameter block */
697
 	memset ( &cpb, 0, sizeof ( cpb ) );
735
 	memset ( &cpb, 0, sizeof ( cpb ) );
698
 	memcpy ( cpb.StationAddr, netdev->ll_addr,
736
 	memcpy ( cpb.StationAddr, netdev->ll_addr,
699
 		 netdev->ll_protocol->ll_addr_len );
737
 		 netdev->ll_protocol->ll_addr_len );
700
 
738
 
701
 	/* Issue command */
739
 	/* Issue command */
702
-	if ( ( stat = nii_issue_cpb ( nii, PXE_OPCODE_STATION_ADDRESS,
703
-				      &cpb, sizeof ( cpb ) ) ) < 0 ) {
740
+	op = NII_OP ( PXE_OPCODE_STATION_ADDRESS,
741
+	              PXE_OPFLAGS_STATION_ADDRESS_WRITE );
742
+	if ( ( stat = nii_issue_cpb ( nii, op, &cpb, sizeof ( cpb ) ) ) < 0 ) {
704
 		rc = -EIO_STAT ( stat );
743
 		rc = -EIO_STAT ( stat );
705
 		DBGC ( nii, "NII %s could not set station address: %s\n",
744
 		DBGC ( nii, "NII %s could not set station address: %s\n",
706
 		       nii->dev.name, strerror ( rc ) );
745
 		       nii->dev.name, strerror ( rc ) );
717
  * @ret rc		Return status code
756
  * @ret rc		Return status code
718
  */
757
  */
719
 static int nii_set_rx_filters ( struct nii_nic *nii ) {
758
 static int nii_set_rx_filters ( struct nii_nic *nii ) {
759
+	uint32_t implementation = nii->undi->Implementation;
720
 	unsigned int flags;
760
 	unsigned int flags;
721
 	unsigned int op;
761
 	unsigned int op;
722
 	int stat;
762
 	int stat;
724
 
764
 
725
 	/* Construct receive filter set */
765
 	/* Construct receive filter set */
726
 	flags = ( PXE_OPFLAGS_RECEIVE_FILTER_ENABLE |
766
 	flags = ( PXE_OPFLAGS_RECEIVE_FILTER_ENABLE |
727
-		  PXE_OPFLAGS_RECEIVE_FILTER_UNICAST |
728
-		  PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST |
729
-		  PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS |
730
-		  PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST );
767
+		  PXE_OPFLAGS_RECEIVE_FILTER_UNICAST );
768
+	if ( implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED )
769
+		flags |= PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST;
770
+	if ( implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED )
771
+		flags |= PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS;
772
+	if ( implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED )
773
+		flags |= PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST;
731
 
774
 
732
 	/* Issue command */
775
 	/* Issue command */
733
 	op = NII_OP ( PXE_OPCODE_RECEIVE_FILTERS, flags );
776
 	op = NII_OP ( PXE_OPCODE_RECEIVE_FILTERS, flags );
752
 			  struct io_buffer *iobuf ) {
795
 			  struct io_buffer *iobuf ) {
753
 	struct nii_nic *nii = netdev->priv;
796
 	struct nii_nic *nii = netdev->priv;
754
 	PXE_CPB_TRANSMIT cpb;
797
 	PXE_CPB_TRANSMIT cpb;
798
+	unsigned int op;
755
 	int stat;
799
 	int stat;
756
 	int rc;
800
 	int rc;
757
 
801
 
768
 	cpb.MediaheaderLen = netdev->ll_protocol->ll_header_len;
812
 	cpb.MediaheaderLen = netdev->ll_protocol->ll_header_len;
769
 
813
 
770
 	/* Transmit packet */
814
 	/* Transmit packet */
771
-	if ( ( stat = nii_issue_cpb ( nii, PXE_OPCODE_TRANSMIT, &cpb,
772
-				      sizeof ( cpb ) ) ) < 0 ) {
815
+	op = NII_OP ( PXE_OPCODE_TRANSMIT,
816
+		      ( PXE_OPFLAGS_TRANSMIT_WHOLE |
817
+			PXE_OPFLAGS_TRANSMIT_DONT_BLOCK ) );
818
+	if ( ( stat = nii_issue_cpb ( nii, op, &cpb, sizeof ( cpb ) ) ) < 0 ) {
773
 		rc = -EIO_STAT ( stat );
819
 		rc = -EIO_STAT ( stat );
774
 		DBGC ( nii, "NII %s could not transmit: %s\n",
820
 		DBGC ( nii, "NII %s could not transmit: %s\n",
775
 		       nii->dev.name, strerror ( rc ) );
821
 		       nii->dev.name, strerror ( rc ) );
924
 	struct nii_nic *nii = netdev->priv;
970
 	struct nii_nic *nii = netdev->priv;
925
 	int rc;
971
 	int rc;
926
 
972
 
927
-	/* Initialise NIC */
928
-	if ( ( rc = nii_initialise ( nii ) ) != 0 )
973
+	/* Initialise NIC
974
+	 *
975
+	 * Some Emulex NII drivers have a bug which prevents packets
976
+	 * from being sent or received unless we specifically ask it
977
+	 * to detect cable presence during initialisation.  Work
978
+	 * around these buggy drivers by requesting cable detection at
979
+	 * this point, even though we don't care about link state here
980
+	 * (and would prefer to have the NIC initialise even if no
981
+	 * cable is present, to match the behaviour of all other iPXE
982
+	 * drivers).
983
+	 */
984
+	if ( ( rc = nii_initialise_and_detect ( nii ) ) != 0 )
929
 		goto err_initialise;
985
 		goto err_initialise;
930
 
986
 
931
 	/* Attempt to set station address */
987
 	/* Attempt to set station address */

Loading…
Cancel
Save