Skip to content

Commit c3168ca

Browse files
Ganesh Goudardavem330
authored andcommitted
cxgb4/cxgbvf: Handle 32-bit fw port capabilities
Implement new 32-bit Firmware Port Capabilities in order to handle new speeds which couldn't be represented in the old 16-bit Firmware Port Capabilities values. Based on the original work of Casey Leedom <[email protected]> Signed-off-by: Ganesh Goudar <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 274043c commit c3168ca

File tree

8 files changed

+1220
-356
lines changed

8 files changed

+1220
-356
lines changed

drivers/net/ethernet/chelsio/cxgb4/cxgb4.h

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -104,13 +104,13 @@ enum dev_state {
104104
DEV_STATE_ERR
105105
};
106106

107-
enum {
107+
enum cc_pause {
108108
PAUSE_RX = 1 << 0,
109109
PAUSE_TX = 1 << 1,
110110
PAUSE_AUTONEG = 1 << 2
111111
};
112112

113-
enum {
113+
enum cc_fec {
114114
FEC_AUTO = 1 << 0, /* IEEE 802.3 "automatic" */
115115
FEC_RS = 1 << 1, /* Reed-Solomon */
116116
FEC_BASER_RS = 1 << 2 /* BaseR/Reed-Solomon */
@@ -366,6 +366,7 @@ struct adapter_params {
366366
unsigned int max_ordird_qp; /* Max read depth per RDMA QP */
367367
unsigned int max_ird_adapter; /* Max read depth per adapter */
368368
bool fr_nsmr_tpte_wr_support; /* FW support for FR_NSMR_TPTE_WR */
369+
u8 fw_caps_support; /* 32-bit Port Capabilities */
369370

370371
/* MPS Buffer Group Map[per Port]. Bit i is set if buffer group i is
371372
* used by the Port
@@ -439,18 +440,34 @@ struct trace_params {
439440
unsigned char port;
440441
};
441442

443+
/* Firmware Port Capabilities types. */
444+
445+
typedef u16 fw_port_cap16_t; /* 16-bit Port Capabilities integral value */
446+
typedef u32 fw_port_cap32_t; /* 32-bit Port Capabilities integral value */
447+
448+
enum fw_caps {
449+
FW_CAPS_UNKNOWN = 0, /* 0'ed out initial state */
450+
FW_CAPS16 = 1, /* old Firmware: 16-bit Port Capabilities */
451+
FW_CAPS32 = 2, /* new Firmware: 32-bit Port Capabilities */
452+
};
453+
442454
struct link_config {
443-
unsigned short supported; /* link capabilities */
444-
unsigned short advertising; /* advertised capabilities */
445-
unsigned short lp_advertising; /* peer advertised capabilities */
446-
unsigned int requested_speed; /* speed user has requested */
447-
unsigned int speed; /* actual link speed */
448-
unsigned char requested_fc; /* flow control user has requested */
449-
unsigned char fc; /* actual link flow control */
450-
unsigned char auto_fec; /* Forward Error Correction: */
451-
unsigned char requested_fec; /* "automatic" (IEEE 802.3), */
452-
unsigned char fec; /* requested, and actual in use */
455+
fw_port_cap32_t pcaps; /* link capabilities */
456+
fw_port_cap32_t def_acaps; /* default advertised capabilities */
457+
fw_port_cap32_t acaps; /* advertised capabilities */
458+
fw_port_cap32_t lpacaps; /* peer advertised capabilities */
459+
460+
fw_port_cap32_t speed_caps; /* speed(s) user has requested */
461+
unsigned int speed; /* actual link speed (Mb/s) */
462+
463+
enum cc_pause requested_fc; /* flow control user has requested */
464+
enum cc_pause fc; /* actual link flow control */
465+
466+
enum cc_fec requested_fec; /* Forward Error Correction: */
467+
enum cc_fec fec; /* requested and actual in use */
468+
453469
unsigned char autoneg; /* autonegotiating? */
470+
454471
unsigned char link_ok; /* link up? */
455472
unsigned char link_down_rc; /* link down reason */
456473
};
@@ -1580,6 +1597,8 @@ int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
15801597
int t4_sge_ctxt_flush(struct adapter *adap, unsigned int mbox);
15811598
void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl);
15821599
int t4_update_port_info(struct port_info *pi);
1600+
int t4_get_link_params(struct port_info *pi, unsigned int *link_okp,
1601+
unsigned int *speedp, unsigned int *mtup);
15831602
int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl);
15841603
void t4_db_full(struct adapter *adapter);
15851604
void t4_db_dropped(struct adapter *adapter);

drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c

Lines changed: 61 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -533,17 +533,23 @@ static int from_fw_port_mod_type(enum fw_port_type port_type,
533533
static unsigned int speed_to_fw_caps(int speed)
534534
{
535535
if (speed == 100)
536-
return FW_PORT_CAP_SPEED_100M;
536+
return FW_PORT_CAP32_SPEED_100M;
537537
if (speed == 1000)
538-
return FW_PORT_CAP_SPEED_1G;
538+
return FW_PORT_CAP32_SPEED_1G;
539539
if (speed == 10000)
540-
return FW_PORT_CAP_SPEED_10G;
540+
return FW_PORT_CAP32_SPEED_10G;
541541
if (speed == 25000)
542-
return FW_PORT_CAP_SPEED_25G;
542+
return FW_PORT_CAP32_SPEED_25G;
543543
if (speed == 40000)
544-
return FW_PORT_CAP_SPEED_40G;
544+
return FW_PORT_CAP32_SPEED_40G;
545+
if (speed == 50000)
546+
return FW_PORT_CAP32_SPEED_50G;
545547
if (speed == 100000)
546-
return FW_PORT_CAP_SPEED_100G;
548+
return FW_PORT_CAP32_SPEED_100G;
549+
if (speed == 200000)
550+
return FW_PORT_CAP32_SPEED_200G;
551+
if (speed == 400000)
552+
return FW_PORT_CAP32_SPEED_400G;
547553
return 0;
548554
}
549555

@@ -560,12 +566,13 @@ static void fw_caps_to_lmm(enum fw_port_type port_type,
560566
unsigned int fw_caps,
561567
unsigned long *link_mode_mask)
562568
{
563-
#define SET_LMM(__lmm_name) __set_bit(ETHTOOL_LINK_MODE_ ## __lmm_name \
564-
## _BIT, link_mode_mask)
569+
#define SET_LMM(__lmm_name) \
570+
__set_bit(ETHTOOL_LINK_MODE_ ## __lmm_name ## _BIT, \
571+
link_mode_mask)
565572

566573
#define FW_CAPS_TO_LMM(__fw_name, __lmm_name) \
567574
do { \
568-
if (fw_caps & FW_PORT_CAP_ ## __fw_name) \
575+
if (fw_caps & FW_PORT_CAP32_ ## __fw_name) \
569576
SET_LMM(__lmm_name); \
570577
} while (0)
571578

@@ -645,7 +652,10 @@ static void fw_caps_to_lmm(enum fw_port_type port_type,
645652
case FW_PORT_TYPE_KR4_100G:
646653
case FW_PORT_TYPE_CR4_QSFP:
647654
SET_LMM(FIBRE);
648-
SET_LMM(100000baseCR4_Full);
655+
FW_CAPS_TO_LMM(SPEED_40G, 40000baseSR4_Full);
656+
FW_CAPS_TO_LMM(SPEED_25G, 25000baseCR_Full);
657+
FW_CAPS_TO_LMM(SPEED_50G, 50000baseCR2_Full);
658+
FW_CAPS_TO_LMM(SPEED_100G, 100000baseCR4_Full);
649659
break;
650660

651661
default:
@@ -663,8 +673,7 @@ static void fw_caps_to_lmm(enum fw_port_type port_type,
663673
/**
664674
* lmm_to_fw_caps - translate ethtool Link Mode Mask to Firmware
665675
* capabilities
666-
*
667-
* @link_mode_mask: ethtool Link Mode Mask
676+
* @et_lmm: ethtool Link Mode Mask
668677
*
669678
* Translate ethtool Link Mode Mask into a Firmware Port capabilities
670679
* value.
@@ -677,14 +686,15 @@ static unsigned int lmm_to_fw_caps(const unsigned long *link_mode_mask)
677686
do { \
678687
if (test_bit(ETHTOOL_LINK_MODE_ ## __lmm_name ## _BIT, \
679688
link_mode_mask)) \
680-
fw_caps |= FW_PORT_CAP_ ## __fw_name; \
689+
fw_caps |= FW_PORT_CAP32_ ## __fw_name; \
681690
} while (0)
682691

683692
LMM_TO_FW_CAPS(100baseT_Full, SPEED_100M);
684693
LMM_TO_FW_CAPS(1000baseT_Full, SPEED_1G);
685694
LMM_TO_FW_CAPS(10000baseT_Full, SPEED_10G);
686695
LMM_TO_FW_CAPS(40000baseSR4_Full, SPEED_40G);
687696
LMM_TO_FW_CAPS(25000baseCR_Full, SPEED_25G);
697+
LMM_TO_FW_CAPS(50000baseCR2_Full, SPEED_50G);
688698
LMM_TO_FW_CAPS(100000baseCR4_Full, SPEED_100G);
689699

690700
#undef LMM_TO_FW_CAPS
@@ -698,17 +708,17 @@ static int get_link_ksettings(struct net_device *dev,
698708
struct port_info *pi = netdev_priv(dev);
699709
struct ethtool_link_settings *base = &link_ksettings->base;
700710

701-
ethtool_link_ksettings_zero_link_mode(link_ksettings, supported);
702-
ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising);
703-
ethtool_link_ksettings_zero_link_mode(link_ksettings, lp_advertising);
704-
705711
/* For the nonce, the Firmware doesn't send up Port State changes
706712
* when the Virtual Interface attached to the Port is down. So
707713
* if it's down, let's grab any changes.
708714
*/
709715
if (!netif_running(dev))
710716
(void)t4_update_port_info(pi);
711717

718+
ethtool_link_ksettings_zero_link_mode(link_ksettings, supported);
719+
ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising);
720+
ethtool_link_ksettings_zero_link_mode(link_ksettings, lp_advertising);
721+
712722
base->port = from_fw_port_mod_type(pi->port_type, pi->mod_type);
713723

714724
if (pi->mdio_addr >= 0) {
@@ -721,11 +731,11 @@ static int get_link_ksettings(struct net_device *dev,
721731
base->mdio_support = 0;
722732
}
723733

724-
fw_caps_to_lmm(pi->port_type, pi->link_cfg.supported,
734+
fw_caps_to_lmm(pi->port_type, pi->link_cfg.pcaps,
725735
link_ksettings->link_modes.supported);
726-
fw_caps_to_lmm(pi->port_type, pi->link_cfg.advertising,
736+
fw_caps_to_lmm(pi->port_type, pi->link_cfg.acaps,
727737
link_ksettings->link_modes.advertising);
728-
fw_caps_to_lmm(pi->port_type, pi->link_cfg.lp_advertising,
738+
fw_caps_to_lmm(pi->port_type, pi->link_cfg.lpacaps,
729739
link_ksettings->link_modes.lp_advertising);
730740

731741
if (netif_carrier_ok(dev)) {
@@ -736,8 +746,24 @@ static int get_link_ksettings(struct net_device *dev,
736746
base->duplex = DUPLEX_UNKNOWN;
737747
}
738748

749+
if (pi->link_cfg.fc & PAUSE_RX) {
750+
if (pi->link_cfg.fc & PAUSE_TX) {
751+
ethtool_link_ksettings_add_link_mode(link_ksettings,
752+
advertising,
753+
Pause);
754+
} else {
755+
ethtool_link_ksettings_add_link_mode(link_ksettings,
756+
advertising,
757+
Asym_Pause);
758+
}
759+
} else if (pi->link_cfg.fc & PAUSE_TX) {
760+
ethtool_link_ksettings_add_link_mode(link_ksettings,
761+
advertising,
762+
Asym_Pause);
763+
}
764+
739765
base->autoneg = pi->link_cfg.autoneg;
740-
if (pi->link_cfg.supported & FW_PORT_CAP_ANEG)
766+
if (pi->link_cfg.pcaps & FW_PORT_CAP32_ANEG)
741767
ethtool_link_ksettings_add_link_mode(link_ksettings,
742768
supported, Autoneg);
743769
if (pi->link_cfg.autoneg)
@@ -748,8 +774,7 @@ static int get_link_ksettings(struct net_device *dev,
748774
}
749775

750776
static int set_link_ksettings(struct net_device *dev,
751-
const struct ethtool_link_ksettings
752-
*link_ksettings)
777+
const struct ethtool_link_ksettings *link_ksettings)
753778
{
754779
struct port_info *pi = netdev_priv(dev);
755780
struct link_config *lc = &pi->link_cfg;
@@ -762,12 +787,12 @@ static int set_link_ksettings(struct net_device *dev,
762787
if (base->duplex != DUPLEX_FULL)
763788
return -EINVAL;
764789

765-
if (!(lc->supported & FW_PORT_CAP_ANEG)) {
790+
if (!(lc->pcaps & FW_PORT_CAP32_ANEG)) {
766791
/* PHY offers a single speed. See if that's what's
767792
* being requested.
768793
*/
769794
if (base->autoneg == AUTONEG_DISABLE &&
770-
(lc->supported & speed_to_fw_caps(base->speed)))
795+
(lc->pcaps & speed_to_fw_caps(base->speed)))
771796
return 0;
772797
return -EINVAL;
773798
}
@@ -776,18 +801,17 @@ static int set_link_ksettings(struct net_device *dev,
776801
if (base->autoneg == AUTONEG_DISABLE) {
777802
fw_caps = speed_to_fw_caps(base->speed);
778803

779-
if (!(lc->supported & fw_caps))
804+
if (!(lc->pcaps & fw_caps))
780805
return -EINVAL;
781-
lc->requested_speed = fw_caps;
782-
lc->advertising = 0;
806+
lc->speed_caps = fw_caps;
807+
lc->acaps = 0;
783808
} else {
784809
fw_caps =
785-
lmm_to_fw_caps(link_ksettings->link_modes.advertising);
786-
787-
if (!(lc->supported & fw_caps))
810+
lmm_to_fw_caps(link_ksettings->link_modes.advertising);
811+
if (!(lc->pcaps & fw_caps))
788812
return -EINVAL;
789-
lc->requested_speed = 0;
790-
lc->advertising = fw_caps | FW_PORT_CAP_ANEG;
813+
lc->speed_caps = 0;
814+
lc->acaps = fw_caps | FW_PORT_CAP32_ANEG;
791815
}
792816
lc->autoneg = base->autoneg;
793817

@@ -806,9 +830,9 @@ static inline unsigned int fwcap_to_eth_fec(unsigned int fw_fec)
806830
{
807831
unsigned int eth_fec = 0;
808832

809-
if (fw_fec & FW_PORT_CAP_FEC_RS)
833+
if (fw_fec & FW_PORT_CAP32_FEC_RS)
810834
eth_fec |= ETHTOOL_FEC_RS;
811-
if (fw_fec & FW_PORT_CAP_FEC_BASER_RS)
835+
if (fw_fec & FW_PORT_CAP32_FEC_BASER_RS)
812836
eth_fec |= ETHTOOL_FEC_BASER;
813837

814838
/* if nothing is set, then FEC is off */
@@ -864,7 +888,7 @@ static int get_fecparam(struct net_device *dev, struct ethtool_fecparam *fec)
864888
* always support IEEE 802.3 "automatic" selection of Link FEC type if
865889
* any FEC is supported.
866890
*/
867-
fec->fec = fwcap_to_eth_fec(lc->supported);
891+
fec->fec = fwcap_to_eth_fec(lc->pcaps);
868892
if (fec->fec != ETHTOOL_FEC_OFF)
869893
fec->fec |= ETHTOOL_FEC_AUTO;
870894

@@ -917,7 +941,7 @@ static int set_pauseparam(struct net_device *dev,
917941

918942
if (epause->autoneg == AUTONEG_DISABLE)
919943
lc->requested_fc = 0;
920-
else if (lc->supported & FW_PORT_CAP_ANEG)
944+
else if (lc->pcaps & FW_PORT_CAP32_ANEG)
921945
lc->requested_fc = PAUSE_AUTONEG;
922946
else
923947
return -EINVAL;

0 commit comments

Comments
 (0)