Skip to content

Commit

Permalink
net: thunderx: Add RGMII interface type support
Browse files Browse the repository at this point in the history
This patch adds RGX/RGMII interface type support to BGX
driver. This type of interface is supported by 81xx SOC.

CN81XX VNIC has 8 VFs and max possible LMAC interfaces are 9,
hence RGMII interface will not work if all DLMs are in BGX mode
and all 8 LMACs are enabled

Signed-off-by: Sunil Goutham <sgoutham@cavium.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Sunil Goutham authored and David S. Miller committed Aug 13, 2016
1 parent 3f8057c commit 6465859
Show file tree
Hide file tree
Showing 6 changed files with 332 additions and 33 deletions.
10 changes: 10 additions & 0 deletions drivers/net/ethernet/cavium/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,20 @@ config THUNDER_NIC_BGX
depends on 64BIT
select PHYLIB
select MDIO_THUNDER
select THUNDER_NIC_RGX
---help---
This driver supports programming and controlling of MAC
interface from NIC physical function driver.

config THUNDER_NIC_RGX
tristate "Thunder MAC interface driver (RGX)"
depends on 64BIT
select PHYLIB
select MDIO_THUNDER
---help---
This driver supports configuring XCV block of RGX interface
present on CN81XX chip.

config LIQUIDIO
tristate "Cavium LiquidIO support"
depends on 64BIT
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/cavium/thunder/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# Makefile for Cavium's Thunder ethernet device
#

obj-$(CONFIG_THUNDER_NIC_RGX) += thunder_xcv.o
obj-$(CONFIG_THUNDER_NIC_BGX) += thunder_bgx.o
obj-$(CONFIG_THUNDER_NIC_PF) += nicpf.o
obj-$(CONFIG_THUNDER_NIC_VF) += nicvf.o
Expand Down
14 changes: 10 additions & 4 deletions drivers/net/ethernet/cavium/thunder/nic_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,14 @@ static void nic_set_lmac_vf_mapping(struct nicpf *nic)
nic_reg_write(nic,
NIC_PF_LMAC_0_7_CREDIT + (lmac * 8),
lmac_credit);

/* On CN81XX there are only 8 VFs but max possible no of
* interfaces are 9.
*/
if (nic->num_vf_en >= pci_sriov_get_totalvfs(nic->pdev)) {
nic->num_vf_en = pci_sriov_get_totalvfs(nic->pdev);
break;
}
}
}

Expand Down Expand Up @@ -450,10 +458,8 @@ static void nic_config_cpi(struct nicpf *nic, struct cpi_cfg_msg *cfg)
lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vnic]);

chan = (lmac * hw->chans_per_lmac) + (bgx * hw->chans_per_bgx);
cpi_base = (lmac * NIC_MAX_CPI_PER_LMAC) +
(bgx * (hw->cpi_cnt / hw->bgx_cnt));
rssi_base = (lmac * hw->rss_ind_tbl_size) +
(bgx * (hw->rssi_cnt / hw->bgx_cnt));
cpi_base = vnic * NIC_MAX_CPI_PER_LMAC;
rssi_base = vnic * hw->rss_ind_tbl_size;

/* Rx channel configuration */
nic_reg_write(nic, NIC_PF_CHAN_0_255_RX_BP_CFG | (chan << 3),
Expand Down
97 changes: 69 additions & 28 deletions drivers/net/ethernet/cavium/thunder/thunder_bgx.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,11 @@ struct bgx {
u8 bgx_id;
struct lmac lmac[MAX_LMAC_PER_BGX];
int lmac_count;
u8 max_lmac;
void __iomem *reg_base;
struct pci_dev *pdev;
bool is_81xx;
bool is_rgx;
};

static struct bgx *bgx_vnic[MAX_BGX_THUNDER];
Expand All @@ -61,6 +63,7 @@ static int bgx_xaui_check_link(struct lmac *lmac);
/* Supported devices */
static const struct pci_device_id bgx_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVICE_ID_THUNDER_BGX) },
{ PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVICE_ID_THUNDER_RGX) },
{ 0, } /* end of table */
};

Expand Down Expand Up @@ -124,7 +127,7 @@ unsigned bgx_get_map(int node)
int i;
unsigned map = 0;

for (i = 0; i < MAX_BGX_PER_CN88XX; i++) {
for (i = 0; i < MAX_BGX_PER_CN81XX; i++) {
if (bgx_vnic[(node * MAX_BGX_PER_CN88XX) + i])
map |= (1 << i);
}
Expand Down Expand Up @@ -189,17 +192,22 @@ EXPORT_SYMBOL(bgx_set_lmac_mac);
void bgx_lmac_rx_tx_enable(int node, int bgx_idx, int lmacid, bool enable)
{
struct bgx *bgx = bgx_vnic[(node * MAX_BGX_PER_CN88XX) + bgx_idx];
struct lmac *lmac;
u64 cfg;

if (!bgx)
return;
lmac = &bgx->lmac[lmacid];

cfg = bgx_reg_read(bgx, lmacid, BGX_CMRX_CFG);
if (enable)
cfg |= CMR_PKT_RX_EN | CMR_PKT_TX_EN;
else
cfg &= ~(CMR_PKT_RX_EN | CMR_PKT_TX_EN);
bgx_reg_write(bgx, lmacid, BGX_CMRX_CFG, cfg);

if (bgx->is_rgx)
xcv_setup_link(enable ? lmac->link_up : 0, lmac->last_speed);
}
EXPORT_SYMBOL(bgx_lmac_rx_tx_enable);

Expand Down Expand Up @@ -266,9 +274,12 @@ static void bgx_sgmii_change_link_state(struct lmac *lmac)

port_cfg = bgx_reg_read(bgx, lmac->lmacid, BGX_GMP_GMI_PRTX_CFG);

/* renable lmac */
/* Re-enable lmac */
cmr_cfg |= CMR_EN;
bgx_reg_write(bgx, lmac->lmacid, BGX_CMRX_CFG, cmr_cfg);

if (bgx->is_rgx && (cmr_cfg & (CMR_PKT_RX_EN | CMR_PKT_TX_EN)))
xcv_setup_link(lmac->link_up, lmac->last_speed);
}

static void bgx_lmac_handler(struct net_device *netdev)
Expand Down Expand Up @@ -418,10 +429,12 @@ static int bgx_lmac_sgmii_init(struct bgx *bgx, struct lmac *lmac)
return 0;
}

if (bgx_poll_reg(bgx, lmacid, BGX_GMP_PCS_MRX_STATUS,
PCS_MRX_STATUS_AN_CPT, false)) {
dev_err(&bgx->pdev->dev, "BGX AN_CPT not completed\n");
return -1;
if (lmac->lmac_type == BGX_MODE_SGMII) {
if (bgx_poll_reg(bgx, lmacid, BGX_GMP_PCS_MRX_STATUS,
PCS_MRX_STATUS_AN_CPT, false)) {
dev_err(&bgx->pdev->dev, "BGX AN_CPT not completed\n");
return -1;
}
}

return 0;
Expand Down Expand Up @@ -663,6 +676,8 @@ static int phy_interface_mode(u8 lmac_type)
{
if (lmac_type == BGX_MODE_QSGMII)
return PHY_INTERFACE_MODE_QSGMII;
if (lmac_type == BGX_MODE_RGMII)
return PHY_INTERFACE_MODE_RGMII;

return PHY_INTERFACE_MODE_SGMII;
}
Expand All @@ -676,7 +691,8 @@ static int bgx_lmac_enable(struct bgx *bgx, u8 lmacid)
lmac->bgx = bgx;

if ((lmac->lmac_type == BGX_MODE_SGMII) ||
(lmac->lmac_type == BGX_MODE_QSGMII)) {
(lmac->lmac_type == BGX_MODE_QSGMII) ||
(lmac->lmac_type == BGX_MODE_RGMII)) {
lmac->is_sgmii = 1;
if (bgx_lmac_sgmii_init(bgx, lmac))
return -1;
Expand Down Expand Up @@ -829,7 +845,7 @@ static void bgx_print_qlm_mode(struct bgx *bgx, u8 lmacid)
char str[20];
u8 dlm;

if (lmacid > MAX_LMAC_PER_BGX)
if (lmacid > bgx->max_lmac)
return;

lmac = &bgx->lmac[lmacid];
Expand Down Expand Up @@ -870,6 +886,9 @@ static void bgx_print_qlm_mode(struct bgx *bgx, u8 lmacid)
return;
dev_info(dev, "%s: QSGMII\n", (char *)str);
break;
case BGX_MODE_RGMII:
dev_info(dev, "%s: RGMII\n", (char *)str);
break;
case BGX_MODE_INVALID:
/* Nothing to do */
break;
Expand All @@ -885,6 +904,7 @@ static void lmac_set_lane2sds(struct bgx *bgx, struct lmac *lmac)
break;
case BGX_MODE_XAUI:
case BGX_MODE_XLAUI:
case BGX_MODE_RGMII:
lmac->lane_to_sds = 0xE4;
break;
case BGX_MODE_RXAUI:
Expand All @@ -904,6 +924,18 @@ static void lmac_set_lane2sds(struct bgx *bgx, struct lmac *lmac)
}
}

static void lmac_set_training(struct bgx *bgx, struct lmac *lmac, int lmacid)
{
if ((lmac->lmac_type != BGX_MODE_10G_KR) &&
(lmac->lmac_type != BGX_MODE_40G_KR)) {
lmac->use_training = 0;
return;
}

lmac->use_training = bgx_reg_read(bgx, lmacid, BGX_SPUX_BR_PMD_CRTL) &
SPU_PMD_CRTL_TRAIN_EN;
}

static void bgx_set_lmac_config(struct bgx *bgx, u8 idx)
{
struct lmac *lmac;
Expand All @@ -914,15 +946,15 @@ static void bgx_set_lmac_config(struct bgx *bgx, u8 idx)

lmac = &bgx->lmac[idx];

if (!bgx->is_81xx) {
if (!bgx->is_81xx || bgx->is_rgx) {
/* Read LMAC0 type to figure out QLM mode
* This is configured by low level firmware
*/
cmr_cfg = bgx_reg_read(bgx, 0, BGX_CMRX_CFG);
lmac->lmac_type = (cmr_cfg >> 8) & 0x07;
lmac->use_training =
bgx_reg_read(bgx, 0, BGX_SPUX_BR_PMD_CRTL) &
SPU_PMD_CRTL_TRAIN_EN;
if (bgx->is_rgx)
lmac->lmac_type = BGX_MODE_RGMII;
lmac_set_training(bgx, lmac, 0);
lmac_set_lane2sds(bgx, lmac);
return;
}
Expand All @@ -939,17 +971,13 @@ static void bgx_set_lmac_config(struct bgx *bgx, u8 idx)
lmac->lmac_type = BGX_MODE_INVALID;
else
lmac->lmac_type = lmac_type;
lmac->use_training =
bgx_reg_read(bgx, idx, BGX_SPUX_BR_PMD_CRTL) &
SPU_PMD_CRTL_TRAIN_EN;
lmac_set_training(bgx, lmac, lmac->lmacid);
lmac_set_lane2sds(bgx, lmac);

/* Set LMAC type of other lmac on same DLM i.e LMAC 1/3 */
olmac = &bgx->lmac[idx + 1];
olmac->lmac_type = lmac->lmac_type;
olmac->use_training =
bgx_reg_read(bgx, idx + 1, BGX_SPUX_BR_PMD_CRTL) &
SPU_PMD_CRTL_TRAIN_EN;
lmac_set_training(bgx, olmac, olmac->lmacid);
lmac_set_lane2sds(bgx, olmac);
}
}
Expand All @@ -976,21 +1004,22 @@ static void bgx_get_qlm_mode(struct bgx *bgx)
u8 idx;

/* Init all LMAC's type to invalid */
for (idx = 0; idx < MAX_LMAC_PER_BGX; idx++) {
for (idx = 0; idx < bgx->max_lmac; idx++) {
lmac = &bgx->lmac[idx];
lmac->lmac_type = BGX_MODE_INVALID;
lmac->lmacid = idx;
lmac->lmac_type = BGX_MODE_INVALID;
lmac->use_training = false;
}

/* It is assumed that low level firmware sets this value */
bgx->lmac_count = bgx_reg_read(bgx, 0, BGX_CMR_RX_LMACS) & 0x7;
if (bgx->lmac_count > MAX_LMAC_PER_BGX)
bgx->lmac_count = MAX_LMAC_PER_BGX;
if (bgx->lmac_count > bgx->max_lmac)
bgx->lmac_count = bgx->max_lmac;

for (idx = 0; idx < MAX_LMAC_PER_BGX; idx++)
for (idx = 0; idx < bgx->max_lmac; idx++)
bgx_set_lmac_config(bgx, idx);

if (!bgx->is_81xx) {
if (!bgx->is_81xx || bgx->is_rgx) {
bgx_print_qlm_mode(bgx, 0);
return;
}
Expand Down Expand Up @@ -1140,7 +1169,7 @@ static int bgx_init_of_phy(struct bgx *bgx)
}

lmac++;
if (lmac == MAX_LMAC_PER_BGX) {
if (lmac == bgx->max_lmac) {
of_node_put(node);
break;
}
Expand Down Expand Up @@ -1218,10 +1247,22 @@ static int bgx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err = -ENOMEM;
goto err_release_regions;
}
bgx->bgx_id = (pci_resource_start(pdev, PCI_CFG_REG_BAR_NUM) >> 24) & 1;
bgx->bgx_id += nic_get_node_id(pdev) * MAX_BGX_PER_CN88XX;

bgx_vnic[bgx->bgx_id] = bgx;
pci_read_config_word(pdev, PCI_DEVICE_ID, &sdevid);
if (sdevid != PCI_DEVICE_ID_THUNDER_RGX) {
bgx->bgx_id =
(pci_resource_start(pdev, PCI_CFG_REG_BAR_NUM) >> 24) & 1;
bgx->bgx_id += nic_get_node_id(pdev) * MAX_BGX_PER_CN88XX;
bgx->max_lmac = MAX_LMAC_PER_BGX;
bgx_vnic[bgx->bgx_id] = bgx;
} else {
bgx->is_rgx = true;
bgx->max_lmac = 1;
bgx->bgx_id = MAX_BGX_PER_CN81XX - 1;
bgx_vnic[bgx->bgx_id] = bgx;
xcv_init_hw();
}

bgx_get_qlm_mode(bgx);

err = bgx_init_phy(bgx);
Expand Down
6 changes: 5 additions & 1 deletion drivers/net/ethernet/cavium/thunder/thunder_bgx.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

/* PCI device ID */
#define PCI_DEVICE_ID_THUNDER_BGX 0xA026
#define PCI_DEVICE_ID_THUNDER_RGX 0xA054

/* Subsystem device IDs */
#define PCI_SUBSYS_DEVID_88XX_BGX 0xA126
Expand All @@ -19,7 +20,7 @@

#define MAX_BGX_THUNDER 8 /* Max 4 nodes, 2 per node */
#define MAX_BGX_PER_CN88XX 2
#define MAX_BGX_PER_CN81XX 2
#define MAX_BGX_PER_CN81XX 3 /* 2 BGXs + 1 RGX */
#define MAX_BGX_PER_CN83XX 4
#define MAX_LMAC_PER_BGX 4
#define MAX_BGX_CHANS_PER_LMAC 16
Expand Down Expand Up @@ -205,6 +206,9 @@ void bgx_set_lmac_mac(int node, int bgx_idx, int lmacid, const u8 *mac);
void bgx_get_lmac_link_state(int node, int bgx_idx, int lmacid, void *status);
void bgx_lmac_internal_loopback(int node, int bgx_idx,
int lmac_idx, bool enable);
void xcv_init_hw(void);
void xcv_setup_link(bool link_up, int link_speed);

u64 bgx_get_rx_stats(int node, int bgx_idx, int lmac, int idx);
u64 bgx_get_tx_stats(int node, int bgx_idx, int lmac, int idx);
#define BGX_RX_STATS_COUNT 11
Expand Down
Loading

0 comments on commit 6465859

Please sign in to comment.