Commit 9f7aec5f authored by David S. Miller's avatar David S. Miller

Merge branch 'thunderx-fixes'

Sunil Goutham says:

====================
thunderx: miscellaneous fixes

This patch series contains fixes for various issues observed
with BGX and NIC drivers.

Changes from v1:
- Fixed comment syle in the first patch of the series
- Removed 'Increase transmit queue length' patch from the series,
  will recheck if it's a driver or system issue and resubmit.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 83e4bf7a bc69fdfc
...@@ -120,10 +120,9 @@ ...@@ -120,10 +120,9 @@
* Calculated for SCLK of 700Mhz * Calculated for SCLK of 700Mhz
* value written should be a 1/16th of what is expected * value written should be a 1/16th of what is expected
* *
* 1 tick per 0.05usec = value of 2.2 * 1 tick per 0.025usec
* This 10% would be covered in CQ timer thresh value
*/ */
#define NICPF_CLK_PER_INT_TICK 2 #define NICPF_CLK_PER_INT_TICK 1
/* Time to wait before we decide that a SQ is stuck. /* Time to wait before we decide that a SQ is stuck.
* *
......
...@@ -37,6 +37,7 @@ struct nicpf { ...@@ -37,6 +37,7 @@ struct nicpf {
#define NIC_GET_BGX_FROM_VF_LMAC_MAP(map) ((map >> 4) & 0xF) #define NIC_GET_BGX_FROM_VF_LMAC_MAP(map) ((map >> 4) & 0xF)
#define NIC_GET_LMAC_FROM_VF_LMAC_MAP(map) (map & 0xF) #define NIC_GET_LMAC_FROM_VF_LMAC_MAP(map) (map & 0xF)
u8 vf_lmac_map[MAX_LMAC]; u8 vf_lmac_map[MAX_LMAC];
u8 lmac_cnt;
struct delayed_work dwork; struct delayed_work dwork;
struct workqueue_struct *check_link; struct workqueue_struct *check_link;
u8 link[MAX_LMAC]; u8 link[MAX_LMAC];
...@@ -279,6 +280,7 @@ static void nic_set_lmac_vf_mapping(struct nicpf *nic) ...@@ -279,6 +280,7 @@ static void nic_set_lmac_vf_mapping(struct nicpf *nic)
u64 lmac_credit; u64 lmac_credit;
nic->num_vf_en = 0; nic->num_vf_en = 0;
nic->lmac_cnt = 0;
for (bgx = 0; bgx < NIC_MAX_BGX; bgx++) { for (bgx = 0; bgx < NIC_MAX_BGX; bgx++) {
if (!(bgx_map & (1 << bgx))) if (!(bgx_map & (1 << bgx)))
...@@ -288,6 +290,7 @@ static void nic_set_lmac_vf_mapping(struct nicpf *nic) ...@@ -288,6 +290,7 @@ static void nic_set_lmac_vf_mapping(struct nicpf *nic)
nic->vf_lmac_map[next_bgx_lmac++] = nic->vf_lmac_map[next_bgx_lmac++] =
NIC_SET_VF_LMAC_MAP(bgx, lmac); NIC_SET_VF_LMAC_MAP(bgx, lmac);
nic->num_vf_en += lmac_cnt; nic->num_vf_en += lmac_cnt;
nic->lmac_cnt += lmac_cnt;
/* Program LMAC credits */ /* Program LMAC credits */
lmac_credit = (1ull << 1); /* channel credit enable */ lmac_credit = (1ull << 1); /* channel credit enable */
...@@ -715,6 +718,13 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf) ...@@ -715,6 +718,13 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
case NIC_MBOX_MSG_CFG_DONE: case NIC_MBOX_MSG_CFG_DONE:
/* Last message of VF config msg sequence */ /* Last message of VF config msg sequence */
nic->vf_enabled[vf] = true; nic->vf_enabled[vf] = true;
if (vf >= nic->lmac_cnt)
goto unlock;
bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
bgx_lmac_rx_tx_enable(nic->node, bgx, lmac, true);
goto unlock; goto unlock;
case NIC_MBOX_MSG_SHUTDOWN: case NIC_MBOX_MSG_SHUTDOWN:
/* First msg in VF teardown sequence */ /* First msg in VF teardown sequence */
...@@ -722,6 +732,14 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf) ...@@ -722,6 +732,14 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
if (vf >= nic->num_vf_en) if (vf >= nic->num_vf_en)
nic->sqs_used[vf - nic->num_vf_en] = false; nic->sqs_used[vf - nic->num_vf_en] = false;
nic->pqs_vf[vf] = 0; nic->pqs_vf[vf] = 0;
if (vf >= nic->lmac_cnt)
break;
bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
bgx_lmac_rx_tx_enable(nic->node, bgx, lmac, false);
break; break;
case NIC_MBOX_MSG_ALLOC_SQS: case NIC_MBOX_MSG_ALLOC_SQS:
nic_alloc_sqs(nic, &mbx.sqs_alloc); nic_alloc_sqs(nic, &mbx.sqs_alloc);
...@@ -940,7 +958,7 @@ static void nic_poll_for_link(struct work_struct *work) ...@@ -940,7 +958,7 @@ static void nic_poll_for_link(struct work_struct *work)
mbx.link_status.msg = NIC_MBOX_MSG_BGX_LINK_CHANGE; mbx.link_status.msg = NIC_MBOX_MSG_BGX_LINK_CHANGE;
for (vf = 0; vf < nic->num_vf_en; vf++) { for (vf = 0; vf < nic->lmac_cnt; vf++) {
/* Poll only if VF is UP */ /* Poll only if VF is UP */
if (!nic->vf_enabled[vf]) if (!nic->vf_enabled[vf])
continue; continue;
...@@ -1074,8 +1092,7 @@ static void nic_remove(struct pci_dev *pdev) ...@@ -1074,8 +1092,7 @@ static void nic_remove(struct pci_dev *pdev)
if (nic->check_link) { if (nic->check_link) {
/* Destroy work Queue */ /* Destroy work Queue */
cancel_delayed_work(&nic->dwork); cancel_delayed_work_sync(&nic->dwork);
flush_workqueue(nic->check_link);
destroy_workqueue(nic->check_link); destroy_workqueue(nic->check_link);
} }
......
...@@ -112,6 +112,13 @@ static int nicvf_get_settings(struct net_device *netdev, ...@@ -112,6 +112,13 @@ static int nicvf_get_settings(struct net_device *netdev,
cmd->supported = 0; cmd->supported = 0;
cmd->transceiver = XCVR_EXTERNAL; cmd->transceiver = XCVR_EXTERNAL;
if (!nic->link_up) {
cmd->duplex = DUPLEX_UNKNOWN;
ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN);
return 0;
}
if (nic->speed <= 1000) { if (nic->speed <= 1000) {
cmd->port = PORT_MII; cmd->port = PORT_MII;
cmd->autoneg = AUTONEG_ENABLE; cmd->autoneg = AUTONEG_ENABLE;
...@@ -125,6 +132,13 @@ static int nicvf_get_settings(struct net_device *netdev, ...@@ -125,6 +132,13 @@ static int nicvf_get_settings(struct net_device *netdev,
return 0; return 0;
} }
static u32 nicvf_get_link(struct net_device *netdev)
{
struct nicvf *nic = netdev_priv(netdev);
return nic->link_up;
}
static void nicvf_get_drvinfo(struct net_device *netdev, static void nicvf_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *info) struct ethtool_drvinfo *info)
{ {
...@@ -660,7 +674,7 @@ static int nicvf_set_channels(struct net_device *dev, ...@@ -660,7 +674,7 @@ static int nicvf_set_channels(struct net_device *dev,
static const struct ethtool_ops nicvf_ethtool_ops = { static const struct ethtool_ops nicvf_ethtool_ops = {
.get_settings = nicvf_get_settings, .get_settings = nicvf_get_settings,
.get_link = ethtool_op_get_link, .get_link = nicvf_get_link,
.get_drvinfo = nicvf_get_drvinfo, .get_drvinfo = nicvf_get_drvinfo,
.get_msglevel = nicvf_get_msglevel, .get_msglevel = nicvf_get_msglevel,
.set_msglevel = nicvf_set_msglevel, .set_msglevel = nicvf_set_msglevel,
......
...@@ -1057,6 +1057,7 @@ int nicvf_stop(struct net_device *netdev) ...@@ -1057,6 +1057,7 @@ int nicvf_stop(struct net_device *netdev)
netif_carrier_off(netdev); netif_carrier_off(netdev);
netif_tx_stop_all_queues(nic->netdev); netif_tx_stop_all_queues(nic->netdev);
nic->link_up = false;
/* Teardown secondary qsets first */ /* Teardown secondary qsets first */
if (!nic->sqs_mode) { if (!nic->sqs_mode) {
...@@ -1211,9 +1212,6 @@ int nicvf_open(struct net_device *netdev) ...@@ -1211,9 +1212,6 @@ int nicvf_open(struct net_device *netdev)
nic->drv_stats.txq_stop = 0; nic->drv_stats.txq_stop = 0;
nic->drv_stats.txq_wake = 0; nic->drv_stats.txq_wake = 0;
netif_carrier_on(netdev);
netif_tx_start_all_queues(netdev);
return 0; return 0;
cleanup: cleanup:
nicvf_disable_intr(nic, NICVF_INTR_MBOX, 0); nicvf_disable_intr(nic, NICVF_INTR_MBOX, 0);
......
...@@ -592,7 +592,7 @@ void nicvf_cmp_queue_config(struct nicvf *nic, struct queue_set *qs, ...@@ -592,7 +592,7 @@ void nicvf_cmp_queue_config(struct nicvf *nic, struct queue_set *qs,
/* Set threshold value for interrupt generation */ /* Set threshold value for interrupt generation */
nicvf_queue_reg_write(nic, NIC_QSET_CQ_0_7_THRESH, qidx, cq->thresh); nicvf_queue_reg_write(nic, NIC_QSET_CQ_0_7_THRESH, qidx, cq->thresh);
nicvf_queue_reg_write(nic, NIC_QSET_CQ_0_7_CFG2, nicvf_queue_reg_write(nic, NIC_QSET_CQ_0_7_CFG2,
qidx, nic->cq_coalesce_usecs); qidx, CMP_QUEUE_TIMER_THRESH);
} }
/* Configures transmit queue */ /* Configures transmit queue */
......
...@@ -76,7 +76,7 @@ ...@@ -76,7 +76,7 @@
#define CMP_QSIZE CMP_QUEUE_SIZE2 #define CMP_QSIZE CMP_QUEUE_SIZE2
#define CMP_QUEUE_LEN (1ULL << (CMP_QSIZE + 10)) #define CMP_QUEUE_LEN (1ULL << (CMP_QSIZE + 10))
#define CMP_QUEUE_CQE_THRESH 0 #define CMP_QUEUE_CQE_THRESH 0
#define CMP_QUEUE_TIMER_THRESH 220 /* 10usec */ #define CMP_QUEUE_TIMER_THRESH 80 /* ~2usec */
#define RBDR_SIZE RBDR_SIZE0 #define RBDR_SIZE RBDR_SIZE0
#define RCV_BUF_COUNT (1ULL << (RBDR_SIZE + 13)) #define RCV_BUF_COUNT (1ULL << (RBDR_SIZE + 13))
......
...@@ -186,6 +186,23 @@ void bgx_set_lmac_mac(int node, int bgx_idx, int lmacid, const u8 *mac) ...@@ -186,6 +186,23 @@ void bgx_set_lmac_mac(int node, int bgx_idx, int lmacid, const u8 *mac)
} }
EXPORT_SYMBOL(bgx_set_lmac_mac); 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];
u64 cfg;
if (!bgx)
return;
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);
}
EXPORT_SYMBOL(bgx_lmac_rx_tx_enable);
static void bgx_sgmii_change_link_state(struct lmac *lmac) static void bgx_sgmii_change_link_state(struct lmac *lmac)
{ {
struct bgx *bgx = lmac->bgx; struct bgx *bgx = lmac->bgx;
...@@ -612,6 +629,8 @@ static void bgx_poll_for_link(struct work_struct *work) ...@@ -612,6 +629,8 @@ static void bgx_poll_for_link(struct work_struct *work)
lmac->last_duplex = 1; lmac->last_duplex = 1;
} else { } else {
lmac->link_up = 0; lmac->link_up = 0;
lmac->last_speed = SPEED_UNKNOWN;
lmac->last_duplex = DUPLEX_UNKNOWN;
} }
if (lmac->last_link != lmac->link_up) { if (lmac->last_link != lmac->link_up) {
...@@ -654,8 +673,7 @@ static int bgx_lmac_enable(struct bgx *bgx, u8 lmacid) ...@@ -654,8 +673,7 @@ static int bgx_lmac_enable(struct bgx *bgx, u8 lmacid)
} }
/* Enable lmac */ /* Enable lmac */
bgx_reg_modify(bgx, lmacid, BGX_CMRX_CFG, bgx_reg_modify(bgx, lmacid, BGX_CMRX_CFG, CMR_EN);
CMR_EN | CMR_PKT_RX_EN | CMR_PKT_TX_EN);
/* Restore default cfg, incase low level firmware changed it */ /* Restore default cfg, incase low level firmware changed it */
bgx_reg_write(bgx, lmacid, BGX_CMRX_RX_DMAC_CTL, 0x03); bgx_reg_write(bgx, lmacid, BGX_CMRX_RX_DMAC_CTL, 0x03);
...@@ -695,8 +713,7 @@ static void bgx_lmac_disable(struct bgx *bgx, u8 lmacid) ...@@ -695,8 +713,7 @@ static void bgx_lmac_disable(struct bgx *bgx, u8 lmacid)
lmac = &bgx->lmac[lmacid]; lmac = &bgx->lmac[lmacid];
if (lmac->check_link) { if (lmac->check_link) {
/* Destroy work queue */ /* Destroy work queue */
cancel_delayed_work(&lmac->dwork); cancel_delayed_work_sync(&lmac->dwork);
flush_workqueue(lmac->check_link);
destroy_workqueue(lmac->check_link); destroy_workqueue(lmac->check_link);
} }
...@@ -1009,6 +1026,9 @@ static int bgx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1009,6 +1026,9 @@ static int bgx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct bgx *bgx = NULL; struct bgx *bgx = NULL;
u8 lmac; u8 lmac;
/* Load octeon mdio driver */
octeon_mdiobus_force_mod_depencency();
bgx = devm_kzalloc(dev, sizeof(*bgx), GFP_KERNEL); bgx = devm_kzalloc(dev, sizeof(*bgx), GFP_KERNEL);
if (!bgx) if (!bgx)
return -ENOMEM; return -ENOMEM;
......
...@@ -182,6 +182,8 @@ enum MCAST_MODE { ...@@ -182,6 +182,8 @@ enum MCAST_MODE {
#define BCAST_ACCEPT 1 #define BCAST_ACCEPT 1
#define CAM_ACCEPT 1 #define CAM_ACCEPT 1
void octeon_mdiobus_force_mod_depencency(void);
void bgx_lmac_rx_tx_enable(int node, int bgx_idx, int lmacid, bool enable);
void bgx_add_dmac_addr(u64 dmac, int node, int bgx_idx, int lmac); void bgx_add_dmac_addr(u64 dmac, int node, int bgx_idx, int lmac);
unsigned bgx_get_map(int node); unsigned bgx_get_map(int node);
int bgx_get_lmac_count(int node, int bgx); int bgx_get_lmac_count(int node, int bgx);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment