|
@@ -575,9 +575,10 @@ static int nii_get_init_info ( struct nii_nic *nii,
|
575
|
575
|
* Initialise UNDI
|
576
|
576
|
*
|
577
|
577
|
* @v nii NII NIC
|
|
578
|
+ * @v flags Flags
|
578
|
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
|
582
|
PXE_CPB_INITIALIZE cpb;
|
582
|
583
|
PXE_DB_INITIALIZE db;
|
583
|
584
|
unsigned int op;
|
|
@@ -600,8 +601,7 @@ static int nii_initialise ( struct nii_nic *nii ) {
|
600
|
601
|
memset ( &db, 0, sizeof ( db ) );
|
601
|
602
|
|
602
|
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
|
605
|
if ( ( stat = nii_issue_cpb_db ( nii, op, &cpb, sizeof ( cpb ),
|
606
|
606
|
&db, sizeof ( db ) ) ) < 0 ) {
|
607
|
607
|
rc = -EIO_STAT ( stat );
|
|
@@ -618,6 +618,36 @@ static int nii_initialise ( struct nii_nic *nii ) {
|
618
|
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
|
652
|
* Shut down UNDI
|
623
|
653
|
*
|
|
@@ -650,6 +680,7 @@ static void nii_shutdown ( struct nii_nic *nii ) {
|
650
|
680
|
static int nii_get_station_address ( struct nii_nic *nii,
|
651
|
681
|
struct net_device *netdev ) {
|
652
|
682
|
PXE_DB_STATION_ADDRESS db;
|
|
683
|
+ unsigned int op;
|
653
|
684
|
int stat;
|
654
|
685
|
int rc;
|
655
|
686
|
|
|
@@ -658,8 +689,9 @@ static int nii_get_station_address ( struct nii_nic *nii,
|
658
|
689
|
goto err_initialise;
|
659
|
690
|
|
660
|
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
|
695
|
rc = -EIO_STAT ( stat );
|
664
|
696
|
DBGC ( nii, "NII %s could not get station address: %s\n",
|
665
|
697
|
nii->dev.name, strerror ( rc ) );
|
|
@@ -689,18 +721,25 @@ static int nii_get_station_address ( struct nii_nic *nii,
|
689
|
721
|
*/
|
690
|
722
|
static int nii_set_station_address ( struct nii_nic *nii,
|
691
|
723
|
struct net_device *netdev ) {
|
|
724
|
+ uint32_t implementation = nii->undi->Implementation;
|
692
|
725
|
PXE_CPB_STATION_ADDRESS cpb;
|
|
726
|
+ unsigned int op;
|
693
|
727
|
int stat;
|
694
|
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
|
734
|
/* Construct parameter block */
|
697
|
735
|
memset ( &cpb, 0, sizeof ( cpb ) );
|
698
|
736
|
memcpy ( cpb.StationAddr, netdev->ll_addr,
|
699
|
737
|
netdev->ll_protocol->ll_addr_len );
|
700
|
738
|
|
701
|
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
|
743
|
rc = -EIO_STAT ( stat );
|
705
|
744
|
DBGC ( nii, "NII %s could not set station address: %s\n",
|
706
|
745
|
nii->dev.name, strerror ( rc ) );
|
|
@@ -717,6 +756,7 @@ static int nii_set_station_address ( struct nii_nic *nii,
|
717
|
756
|
* @ret rc Return status code
|
718
|
757
|
*/
|
719
|
758
|
static int nii_set_rx_filters ( struct nii_nic *nii ) {
|
|
759
|
+ uint32_t implementation = nii->undi->Implementation;
|
720
|
760
|
unsigned int flags;
|
721
|
761
|
unsigned int op;
|
722
|
762
|
int stat;
|
|
@@ -724,10 +764,13 @@ static int nii_set_rx_filters ( struct nii_nic *nii ) {
|
724
|
764
|
|
725
|
765
|
/* Construct receive filter set */
|
726
|
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
|
775
|
/* Issue command */
|
733
|
776
|
op = NII_OP ( PXE_OPCODE_RECEIVE_FILTERS, flags );
|
|
@@ -752,6 +795,7 @@ static int nii_transmit ( struct net_device *netdev,
|
752
|
795
|
struct io_buffer *iobuf ) {
|
753
|
796
|
struct nii_nic *nii = netdev->priv;
|
754
|
797
|
PXE_CPB_TRANSMIT cpb;
|
|
798
|
+ unsigned int op;
|
755
|
799
|
int stat;
|
756
|
800
|
int rc;
|
757
|
801
|
|
|
@@ -768,8 +812,10 @@ static int nii_transmit ( struct net_device *netdev,
|
768
|
812
|
cpb.MediaheaderLen = netdev->ll_protocol->ll_header_len;
|
769
|
813
|
|
770
|
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
|
819
|
rc = -EIO_STAT ( stat );
|
774
|
820
|
DBGC ( nii, "NII %s could not transmit: %s\n",
|
775
|
821
|
nii->dev.name, strerror ( rc ) );
|
|
@@ -924,8 +970,18 @@ static int nii_open ( struct net_device *netdev ) {
|
924
|
970
|
struct nii_nic *nii = netdev->priv;
|
925
|
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
|
985
|
goto err_initialise;
|
930
|
986
|
|
931
|
987
|
/* Attempt to set station address */
|