Merge branch 'liquidio-CN23XX-part-2'
Raghu Vatsavayi says: ==================== liquidio CN23XX support I am posting the remaining half of patchset after the acceptance of first half. With this patchset I am able to completely submit the code of V3 patchset which you earlier advised me to split into smaller ones. This V5 patch also addresses all the comments from previous submission: 1) Avoid busy loop while reading registers. 2) Other minor comments about debug messages and constants. Please apply patches in following order as some of the patches depend on earlier patches. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
e8a3925f69
|
@ -887,6 +887,67 @@ static irqreturn_t cn23xx_interrupt_handler(void *dev)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void cn23xx_bar1_idx_setup(struct octeon_device *oct, u64 core_addr,
|
||||
u32 idx, int valid)
|
||||
{
|
||||
u64 bar1;
|
||||
u64 reg_adr;
|
||||
|
||||
if (!valid) {
|
||||
reg_adr = lio_pci_readq(
|
||||
oct, CN23XX_PEM_BAR1_INDEX_REG(oct->pcie_port, idx));
|
||||
WRITE_ONCE(bar1, reg_adr);
|
||||
lio_pci_writeq(oct, (READ_ONCE(bar1) & 0xFFFFFFFEULL),
|
||||
CN23XX_PEM_BAR1_INDEX_REG(oct->pcie_port, idx));
|
||||
reg_adr = lio_pci_readq(
|
||||
oct, CN23XX_PEM_BAR1_INDEX_REG(oct->pcie_port, idx));
|
||||
WRITE_ONCE(bar1, reg_adr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* The PEM(0..3)_BAR1_INDEX(0..15)[ADDR_IDX]<23:4> stores
|
||||
* bits <41:22> of the Core Addr
|
||||
*/
|
||||
lio_pci_writeq(oct, (((core_addr >> 22) << 4) | PCI_BAR1_MASK),
|
||||
CN23XX_PEM_BAR1_INDEX_REG(oct->pcie_port, idx));
|
||||
|
||||
WRITE_ONCE(bar1, lio_pci_readq(
|
||||
oct, CN23XX_PEM_BAR1_INDEX_REG(oct->pcie_port, idx)));
|
||||
}
|
||||
|
||||
static void cn23xx_bar1_idx_write(struct octeon_device *oct, u32 idx, u32 mask)
|
||||
{
|
||||
lio_pci_writeq(oct, mask,
|
||||
CN23XX_PEM_BAR1_INDEX_REG(oct->pcie_port, idx));
|
||||
}
|
||||
|
||||
static u32 cn23xx_bar1_idx_read(struct octeon_device *oct, u32 idx)
|
||||
{
|
||||
return (u32)lio_pci_readq(
|
||||
oct, CN23XX_PEM_BAR1_INDEX_REG(oct->pcie_port, idx));
|
||||
}
|
||||
|
||||
/* always call with lock held */
|
||||
static u32 cn23xx_update_read_index(struct octeon_instr_queue *iq)
|
||||
{
|
||||
u32 new_idx;
|
||||
u32 last_done;
|
||||
u32 pkt_in_done = readl(iq->inst_cnt_reg);
|
||||
|
||||
last_done = pkt_in_done - iq->pkt_in_done;
|
||||
iq->pkt_in_done = pkt_in_done;
|
||||
|
||||
/* Modulo of the new index with the IQ size will give us
|
||||
* the new index. The iq->reset_instr_cnt is always zero for
|
||||
* cn23xx, so no extra adjustments are needed.
|
||||
*/
|
||||
new_idx = (iq->octeon_read_index +
|
||||
(u32)(last_done & CN23XX_PKT_IN_DONE_CNT_MASK)) %
|
||||
iq->max_count;
|
||||
|
||||
return new_idx;
|
||||
}
|
||||
|
||||
static void cn23xx_enable_pf_interrupt(struct octeon_device *oct, u8 intr_flag)
|
||||
{
|
||||
struct octeon_cn23xx_pf *cn23xx = (struct octeon_cn23xx_pf *)oct->chip;
|
||||
|
@ -1063,6 +1124,11 @@ int setup_cn23xx_octeon_pf_device(struct octeon_device *oct)
|
|||
|
||||
oct->fn_list.soft_reset = cn23xx_pf_soft_reset;
|
||||
oct->fn_list.setup_device_regs = cn23xx_setup_pf_device_regs;
|
||||
oct->fn_list.update_iq_read_idx = cn23xx_update_read_index;
|
||||
|
||||
oct->fn_list.bar1_idx_setup = cn23xx_bar1_idx_setup;
|
||||
oct->fn_list.bar1_idx_write = cn23xx_bar1_idx_write;
|
||||
oct->fn_list.bar1_idx_read = cn23xx_bar1_idx_read;
|
||||
|
||||
oct->fn_list.enable_interrupt = cn23xx_enable_pf_interrupt;
|
||||
oct->fn_list.disable_interrupt = cn23xx_disable_pf_interrupt;
|
||||
|
|
|
@ -51,6 +51,8 @@ int setup_cn23xx_octeon_pf_device(struct octeon_device *oct);
|
|||
int validate_cn23xx_pf_config_info(struct octeon_device *oct,
|
||||
struct octeon_config *conf23xx);
|
||||
|
||||
u32 cn23xx_pf_get_oq_ticks(struct octeon_device *oct, u32 time_intr_in_us);
|
||||
|
||||
void cn23xx_dump_pf_initialized_regs(struct octeon_device *oct);
|
||||
|
||||
int cn23xx_fw_loaded(struct octeon_device *oct);
|
||||
|
|
|
@ -156,14 +156,19 @@ void liquidio_link_ctrl_cmd_completion(void *nctrl_ptr)
|
|||
dev_info(&oct->pci_dev->dev, "%s MTU Changed from %d to %d\n",
|
||||
netdev->name, netdev->mtu,
|
||||
nctrl->ncmd.s.param1);
|
||||
rtnl_lock();
|
||||
netdev->mtu = nctrl->ncmd.s.param1;
|
||||
call_netdevice_notifiers(NETDEV_CHANGEMTU, netdev);
|
||||
rtnl_unlock();
|
||||
queue_delayed_work(lio->link_status_wq.wq,
|
||||
&lio->link_status_wq.wk.work, 0);
|
||||
break;
|
||||
|
||||
case OCTNET_CMD_GPIO_ACCESS:
|
||||
netif_info(lio, probe, lio->netdev, "LED Flashing visual identification\n");
|
||||
|
||||
break;
|
||||
|
||||
case OCTNET_CMD_ID_ACTIVE:
|
||||
netif_info(lio, probe, lio->netdev, "LED Flashing visual identification\n");
|
||||
|
||||
break;
|
||||
|
||||
case OCTNET_CMD_LRO_ENABLE:
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "octeon_network.h"
|
||||
#include "cn66xx_regs.h"
|
||||
#include "cn66xx_device.h"
|
||||
#include "cn23xx_pf_device.h"
|
||||
|
||||
static int octnet_get_link_stats(struct net_device *netdev);
|
||||
|
||||
|
@ -75,6 +76,7 @@ enum {
|
|||
|
||||
#define ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
|
||||
#define OCT_ETHTOOL_REGDUMP_LEN 4096
|
||||
#define OCT_ETHTOOL_REGDUMP_LEN_23XX (4096 * 11)
|
||||
#define OCT_ETHTOOL_REGSVER 1
|
||||
|
||||
/* statistics of PF */
|
||||
|
@ -188,6 +190,10 @@ static const char oct_droq_stats_strings[][ETH_GSTRING_LEN] = {
|
|||
"buffer_alloc_failure",
|
||||
};
|
||||
|
||||
/* LiquidIO driver private flags */
|
||||
static const char oct_priv_flags_strings[][ETH_GSTRING_LEN] = {
|
||||
};
|
||||
|
||||
#define OCTNIC_NCMD_AUTONEG_ON 0x1
|
||||
#define OCTNIC_NCMD_PHY_ON 0x2
|
||||
|
||||
|
@ -259,6 +265,13 @@ lio_ethtool_get_channels(struct net_device *dev,
|
|||
max_tx = CFG_GET_IQ_MAX_Q(conf6x);
|
||||
rx_count = CFG_GET_NUM_RXQS_NIC_IF(conf6x, lio->ifidx);
|
||||
tx_count = CFG_GET_NUM_TXQS_NIC_IF(conf6x, lio->ifidx);
|
||||
} else if (OCTEON_CN23XX_PF(oct)) {
|
||||
struct octeon_config *conf23 = CHIP_FIELD(oct, cn23xx_pf, conf);
|
||||
|
||||
max_rx = CFG_GET_OQ_MAX_Q(conf23);
|
||||
max_tx = CFG_GET_IQ_MAX_Q(conf23);
|
||||
rx_count = CFG_GET_NUM_RXQS_NIC_IF(conf23, lio->ifidx);
|
||||
tx_count = CFG_GET_NUM_TXQS_NIC_IF(conf23, lio->ifidx);
|
||||
}
|
||||
|
||||
channel->max_rx = max_rx;
|
||||
|
@ -331,6 +344,32 @@ static int octnet_gpio_access(struct net_device *netdev, int addr, int val)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int octnet_id_active(struct net_device *netdev, int val)
|
||||
{
|
||||
struct lio *lio = GET_LIO(netdev);
|
||||
struct octeon_device *oct = lio->oct_dev;
|
||||
struct octnic_ctrl_pkt nctrl;
|
||||
int ret = 0;
|
||||
|
||||
memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
|
||||
|
||||
nctrl.ncmd.u64 = 0;
|
||||
nctrl.ncmd.s.cmd = OCTNET_CMD_ID_ACTIVE;
|
||||
nctrl.ncmd.s.param1 = val;
|
||||
nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
|
||||
nctrl.wait_time = 100;
|
||||
nctrl.netpndev = (u64)netdev;
|
||||
nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
|
||||
|
||||
ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
|
||||
if (ret < 0) {
|
||||
dev_err(&oct->pci_dev->dev, "Failed to configure gpio value\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Callback for when mdio command response arrives
|
||||
*/
|
||||
static void octnet_mdio_resp_callback(struct octeon_device *oct,
|
||||
|
@ -474,6 +513,11 @@ static int lio_set_phys_id(struct net_device *netdev,
|
|||
&value);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else if (oct->chip_id == OCTEON_CN23XX_PF_VID) {
|
||||
octnet_id_active(netdev, LED_IDENTIFICATION_ON);
|
||||
|
||||
/* returns 0 since updates are asynchronous */
|
||||
return 0;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -519,7 +563,10 @@ static int lio_set_phys_id(struct net_device *netdev,
|
|||
&lio->phy_beacon_val);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else if (oct->chip_id == OCTEON_CN23XX_PF_VID) {
|
||||
octnet_id_active(netdev, LED_IDENTIFICATION_OFF);
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -548,6 +595,13 @@ lio_ethtool_get_ringparam(struct net_device *netdev,
|
|||
rx_max_pending = CN6XXX_MAX_OQ_DESCRIPTORS;
|
||||
rx_pending = CFG_GET_NUM_RX_DESCS_NIC_IF(conf6x, lio->ifidx);
|
||||
tx_pending = CFG_GET_NUM_TX_DESCS_NIC_IF(conf6x, lio->ifidx);
|
||||
} else if (OCTEON_CN23XX_PF(oct)) {
|
||||
struct octeon_config *conf23 = CHIP_FIELD(oct, cn23xx_pf, conf);
|
||||
|
||||
tx_max_pending = CN23XX_MAX_IQ_DESCRIPTORS;
|
||||
rx_max_pending = CN23XX_MAX_OQ_DESCRIPTORS;
|
||||
rx_pending = CFG_GET_NUM_RX_DESCS_NIC_IF(conf23, lio->ifidx);
|
||||
tx_pending = CFG_GET_NUM_TX_DESCS_NIC_IF(conf23, lio->ifidx);
|
||||
}
|
||||
|
||||
if (lio->mtu > OCTNET_DEFAULT_FRM_SIZE - OCTNET_FRM_HEADER_SIZE) {
|
||||
|
@ -608,6 +662,69 @@ lio_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause)
|
|||
pause->rx_pause = oct->rx_pause;
|
||||
}
|
||||
|
||||
static int
|
||||
lio_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause)
|
||||
{
|
||||
/* Notes: Not supporting any auto negotiation in these
|
||||
* drivers.
|
||||
*/
|
||||
struct lio *lio = GET_LIO(netdev);
|
||||
struct octeon_device *oct = lio->oct_dev;
|
||||
struct octnic_ctrl_pkt nctrl;
|
||||
struct oct_link_info *linfo = &lio->linfo;
|
||||
|
||||
int ret = 0;
|
||||
|
||||
if (oct->chip_id != OCTEON_CN23XX_PF_VID)
|
||||
return -EINVAL;
|
||||
|
||||
if (linfo->link.s.duplex == 0) {
|
||||
/*no flow control for half duplex*/
|
||||
if (pause->rx_pause || pause->tx_pause)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*do not support autoneg of link flow control*/
|
||||
if (pause->autoneg == AUTONEG_ENABLE)
|
||||
return -EINVAL;
|
||||
|
||||
memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
|
||||
|
||||
nctrl.ncmd.u64 = 0;
|
||||
nctrl.ncmd.s.cmd = OCTNET_CMD_SET_FLOW_CTL;
|
||||
nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
|
||||
nctrl.wait_time = 100;
|
||||
nctrl.netpndev = (u64)netdev;
|
||||
nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
|
||||
|
||||
if (pause->rx_pause) {
|
||||
/*enable rx pause*/
|
||||
nctrl.ncmd.s.param1 = 1;
|
||||
} else {
|
||||
/*disable rx pause*/
|
||||
nctrl.ncmd.s.param1 = 0;
|
||||
}
|
||||
|
||||
if (pause->tx_pause) {
|
||||
/*enable tx pause*/
|
||||
nctrl.ncmd.s.param2 = 1;
|
||||
} else {
|
||||
/*disable tx pause*/
|
||||
nctrl.ncmd.s.param2 = 0;
|
||||
}
|
||||
|
||||
ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
|
||||
if (ret < 0) {
|
||||
dev_err(&oct->pci_dev->dev, "Failed to set pause parameter\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
oct->rx_pause = pause->rx_pause;
|
||||
oct->tx_pause = pause->tx_pause;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
lio_get_ethtool_stats(struct net_device *netdev,
|
||||
struct ethtool_stats *stats __attribute__((unused)),
|
||||
|
@ -875,6 +992,27 @@ lio_get_ethtool_stats(struct net_device *netdev,
|
|||
}
|
||||
}
|
||||
|
||||
static void lio_get_priv_flags_strings(struct lio *lio, u8 *data)
|
||||
{
|
||||
struct octeon_device *oct_dev = lio->oct_dev;
|
||||
int i;
|
||||
|
||||
switch (oct_dev->chip_id) {
|
||||
case OCTEON_CN23XX_PF_VID:
|
||||
for (i = 0; i < ARRAY_SIZE(oct_priv_flags_strings); i++) {
|
||||
sprintf(data, "%s", oct_priv_flags_strings[i]);
|
||||
data += ETH_GSTRING_LEN;
|
||||
}
|
||||
break;
|
||||
case OCTEON_CN68XX:
|
||||
case OCTEON_CN66XX:
|
||||
break;
|
||||
default:
|
||||
netif_info(lio, drv, lio->netdev, "Unknown Chip !!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void lio_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
|
||||
{
|
||||
struct lio *lio = GET_LIO(netdev);
|
||||
|
@ -914,12 +1052,31 @@ static void lio_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
|
|||
}
|
||||
break;
|
||||
|
||||
case ETH_SS_PRIV_FLAGS:
|
||||
lio_get_priv_flags_strings(lio, data);
|
||||
break;
|
||||
default:
|
||||
netif_info(lio, drv, lio->netdev, "Unknown Stringset !!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int lio_get_priv_flags_ss_count(struct lio *lio)
|
||||
{
|
||||
struct octeon_device *oct_dev = lio->oct_dev;
|
||||
|
||||
switch (oct_dev->chip_id) {
|
||||
case OCTEON_CN23XX_PF_VID:
|
||||
return ARRAY_SIZE(oct_priv_flags_strings);
|
||||
case OCTEON_CN68XX:
|
||||
case OCTEON_CN66XX:
|
||||
return -EOPNOTSUPP;
|
||||
default:
|
||||
netif_info(lio, drv, lio->netdev, "Unknown Chip !!\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
static int lio_get_sset_count(struct net_device *netdev, int sset)
|
||||
{
|
||||
struct lio *lio = GET_LIO(netdev);
|
||||
|
@ -930,6 +1087,8 @@ static int lio_get_sset_count(struct net_device *netdev, int sset)
|
|||
return (ARRAY_SIZE(oct_stats_strings) +
|
||||
ARRAY_SIZE(oct_iq_stats_strings) * oct_dev->num_iqs +
|
||||
ARRAY_SIZE(oct_droq_stats_strings) * oct_dev->num_oqs);
|
||||
case ETH_SS_PRIV_FLAGS:
|
||||
return lio_get_priv_flags_ss_count(lio);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
@ -946,6 +1105,16 @@ static int lio_get_intr_coalesce(struct net_device *netdev,
|
|||
intrmod_cfg = &oct->intrmod;
|
||||
|
||||
switch (oct->chip_id) {
|
||||
case OCTEON_CN23XX_PF_VID:
|
||||
if (!intrmod_cfg->rx_enable) {
|
||||
intr_coal->rx_coalesce_usecs = intrmod_cfg->rx_usecs;
|
||||
intr_coal->rx_max_coalesced_frames =
|
||||
intrmod_cfg->rx_frames;
|
||||
}
|
||||
if (!intrmod_cfg->tx_enable)
|
||||
intr_coal->tx_max_coalesced_frames =
|
||||
intrmod_cfg->tx_frames;
|
||||
break;
|
||||
case OCTEON_CN68XX:
|
||||
case OCTEON_CN66XX: {
|
||||
struct octeon_cn6xxx *cn6xxx =
|
||||
|
@ -981,7 +1150,15 @@ static int lio_get_intr_coalesce(struct net_device *netdev,
|
|||
intr_coal->rx_coalesce_usecs_low =
|
||||
intrmod_cfg->rx_mintmr_trigger;
|
||||
intr_coal->rx_max_coalesced_frames_low =
|
||||
intrmod_cfg->rx_mincnt_trigger;
|
||||
intrmod_cfg->rx_mincnt_trigger;
|
||||
}
|
||||
if (OCTEON_CN23XX_PF(oct) &&
|
||||
(intrmod_cfg->tx_enable)) {
|
||||
intr_coal->use_adaptive_tx_coalesce = intrmod_cfg->tx_enable;
|
||||
intr_coal->tx_max_coalesced_frames_high =
|
||||
intrmod_cfg->tx_maxcnt_trigger;
|
||||
intr_coal->tx_max_coalesced_frames_low =
|
||||
intrmod_cfg->tx_mincnt_trigger;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1058,11 +1235,11 @@ static void
|
|||
octnet_nic_stats_callback(struct octeon_device *oct_dev,
|
||||
u32 status, void *ptr)
|
||||
{
|
||||
struct octeon_soft_command *sc = (struct octeon_soft_command *)ptr;
|
||||
struct oct_nic_stats_resp *resp = (struct oct_nic_stats_resp *)
|
||||
sc->virtrptr;
|
||||
struct oct_nic_stats_ctrl *ctrl = (struct oct_nic_stats_ctrl *)
|
||||
sc->ctxptr;
|
||||
struct octeon_soft_command *sc = (struct octeon_soft_command *)ptr;
|
||||
struct oct_nic_stats_resp *resp =
|
||||
(struct oct_nic_stats_resp *)sc->virtrptr;
|
||||
struct oct_nic_stats_ctrl *ctrl =
|
||||
(struct oct_nic_stats_ctrl *)sc->ctxptr;
|
||||
struct nic_rx_stats *rsp_rstats = &resp->stats.fromwire;
|
||||
struct nic_tx_stats *rsp_tstats = &resp->stats.fromhost;
|
||||
|
||||
|
@ -1312,6 +1489,27 @@ oct_cfg_rx_intrcnt(struct lio *lio, struct ethtool_coalesce *intr_coal)
|
|||
CFG_SET_OQ_INTR_PKT(cn6xxx->conf, rx_max_coalesced_frames);
|
||||
break;
|
||||
}
|
||||
case OCTEON_CN23XX_PF_VID: {
|
||||
int q_no;
|
||||
|
||||
if (!intr_coal->rx_max_coalesced_frames)
|
||||
rx_max_coalesced_frames = oct->intrmod.rx_frames;
|
||||
else
|
||||
rx_max_coalesced_frames =
|
||||
intr_coal->rx_max_coalesced_frames;
|
||||
for (q_no = 0; q_no < oct->num_oqs; q_no++) {
|
||||
q_no += oct->sriov_info.pf_srn;
|
||||
octeon_write_csr64(
|
||||
oct, CN23XX_SLI_OQ_PKT_INT_LEVELS(q_no),
|
||||
(octeon_read_csr64(
|
||||
oct, CN23XX_SLI_OQ_PKT_INT_LEVELS(q_no)) &
|
||||
(0x3fffff00000000UL)) |
|
||||
rx_max_coalesced_frames);
|
||||
/*consider setting resend bit*/
|
||||
}
|
||||
oct->intrmod.rx_frames = rx_max_coalesced_frames;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -1344,6 +1542,27 @@ static int oct_cfg_rx_intrtime(struct lio *lio,
|
|||
CFG_SET_OQ_INTR_TIME(cn6xxx->conf, rx_coalesce_usecs);
|
||||
break;
|
||||
}
|
||||
case OCTEON_CN23XX_PF_VID: {
|
||||
u64 time_threshold;
|
||||
int q_no;
|
||||
|
||||
if (!intr_coal->rx_coalesce_usecs)
|
||||
rx_coalesce_usecs = oct->intrmod.rx_usecs;
|
||||
else
|
||||
rx_coalesce_usecs = intr_coal->rx_coalesce_usecs;
|
||||
time_threshold =
|
||||
cn23xx_pf_get_oq_ticks(oct, (u32)rx_coalesce_usecs);
|
||||
for (q_no = 0; q_no < oct->num_oqs; q_no++) {
|
||||
q_no += oct->sriov_info.pf_srn;
|
||||
octeon_write_csr64(oct,
|
||||
CN23XX_SLI_OQ_PKT_INT_LEVELS(q_no),
|
||||
(oct->intrmod.rx_frames |
|
||||
(time_threshold << 32)));
|
||||
/*consider writing to resend bit here*/
|
||||
}
|
||||
oct->intrmod.rx_usecs = rx_coalesce_usecs;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -1356,12 +1575,37 @@ oct_cfg_tx_intrcnt(struct lio *lio, struct ethtool_coalesce *intr_coal
|
|||
__attribute__((unused)))
|
||||
{
|
||||
struct octeon_device *oct = lio->oct_dev;
|
||||
u32 iq_intr_pkt;
|
||||
void __iomem *inst_cnt_reg;
|
||||
u64 val;
|
||||
|
||||
/* Config Cnt based interrupt values */
|
||||
switch (oct->chip_id) {
|
||||
case OCTEON_CN68XX:
|
||||
case OCTEON_CN66XX:
|
||||
break;
|
||||
case OCTEON_CN23XX_PF_VID: {
|
||||
int q_no;
|
||||
|
||||
if (!intr_coal->tx_max_coalesced_frames)
|
||||
iq_intr_pkt = CN23XX_DEF_IQ_INTR_THRESHOLD &
|
||||
CN23XX_PKT_IN_DONE_WMARK_MASK;
|
||||
else
|
||||
iq_intr_pkt = intr_coal->tx_max_coalesced_frames &
|
||||
CN23XX_PKT_IN_DONE_WMARK_MASK;
|
||||
for (q_no = 0; q_no < oct->num_iqs; q_no++) {
|
||||
inst_cnt_reg = (oct->instr_queue[q_no])->inst_cnt_reg;
|
||||
val = readq(inst_cnt_reg);
|
||||
/*clear wmark and count.dont want to write count back*/
|
||||
val = (val & 0xFFFF000000000000ULL) |
|
||||
((u64)iq_intr_pkt
|
||||
<< CN23XX_PKT_IN_DONE_WMARK_BIT_POS);
|
||||
writeq(val, inst_cnt_reg);
|
||||
/*consider setting resend bit*/
|
||||
}
|
||||
oct->intrmod.tx_frames = iq_intr_pkt;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -1397,6 +1641,8 @@ static int lio_set_intr_coalesce(struct net_device *netdev,
|
|||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case OCTEON_CN23XX_PF_VID:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -1539,9 +1785,237 @@ static int lio_nway_reset(struct net_device *netdev)
|
|||
}
|
||||
|
||||
/* Return register dump len. */
|
||||
static int lio_get_regs_len(struct net_device *dev __attribute__((unused)))
|
||||
static int lio_get_regs_len(struct net_device *dev)
|
||||
{
|
||||
return OCT_ETHTOOL_REGDUMP_LEN;
|
||||
struct lio *lio = GET_LIO(dev);
|
||||
struct octeon_device *oct = lio->oct_dev;
|
||||
|
||||
switch (oct->chip_id) {
|
||||
case OCTEON_CN23XX_PF_VID:
|
||||
return OCT_ETHTOOL_REGDUMP_LEN_23XX;
|
||||
default:
|
||||
return OCT_ETHTOOL_REGDUMP_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
static int cn23xx_read_csr_reg(char *s, struct octeon_device *oct)
|
||||
{
|
||||
u32 reg;
|
||||
u8 pf_num = oct->pf_num;
|
||||
int len = 0;
|
||||
int i;
|
||||
|
||||
/* PCI Window Registers */
|
||||
|
||||
len += sprintf(s + len, "\n\t Octeon CSR Registers\n\n");
|
||||
|
||||
/*0x29030 or 0x29040*/
|
||||
reg = CN23XX_SLI_PKT_MAC_RINFO64(oct->pcie_port, oct->pf_num);
|
||||
len += sprintf(s + len,
|
||||
"\n[%08x] (SLI_PKT_MAC%d_PF%d_RINFO): %016llx\n",
|
||||
reg, oct->pcie_port, oct->pf_num,
|
||||
(u64)octeon_read_csr64(oct, reg));
|
||||
|
||||
/*0x27080 or 0x27090*/
|
||||
reg = CN23XX_SLI_MAC_PF_INT_ENB64(oct->pcie_port, oct->pf_num);
|
||||
len +=
|
||||
sprintf(s + len, "\n[%08x] (SLI_MAC%d_PF%d_INT_ENB): %016llx\n",
|
||||
reg, oct->pcie_port, oct->pf_num,
|
||||
(u64)octeon_read_csr64(oct, reg));
|
||||
|
||||
/*0x27000 or 0x27010*/
|
||||
reg = CN23XX_SLI_MAC_PF_INT_SUM64(oct->pcie_port, oct->pf_num);
|
||||
len +=
|
||||
sprintf(s + len, "\n[%08x] (SLI_MAC%d_PF%d_INT_SUM): %016llx\n",
|
||||
reg, oct->pcie_port, oct->pf_num,
|
||||
(u64)octeon_read_csr64(oct, reg));
|
||||
|
||||
/*0x29120*/
|
||||
reg = 0x29120;
|
||||
len += sprintf(s + len, "\n[%08x] (SLI_PKT_MEM_CTL): %016llx\n", reg,
|
||||
(u64)octeon_read_csr64(oct, reg));
|
||||
|
||||
/*0x27300*/
|
||||
reg = 0x27300 + oct->pcie_port * CN23XX_MAC_INT_OFFSET +
|
||||
(oct->pf_num) * CN23XX_PF_INT_OFFSET;
|
||||
len += sprintf(
|
||||
s + len, "\n[%08x] (SLI_MAC%d_PF%d_PKT_VF_INT): %016llx\n", reg,
|
||||
oct->pcie_port, oct->pf_num, (u64)octeon_read_csr64(oct, reg));
|
||||
|
||||
/*0x27200*/
|
||||
reg = 0x27200 + oct->pcie_port * CN23XX_MAC_INT_OFFSET +
|
||||
(oct->pf_num) * CN23XX_PF_INT_OFFSET;
|
||||
len += sprintf(s + len,
|
||||
"\n[%08x] (SLI_MAC%d_PF%d_PP_VF_INT): %016llx\n",
|
||||
reg, oct->pcie_port, oct->pf_num,
|
||||
(u64)octeon_read_csr64(oct, reg));
|
||||
|
||||
/*29130*/
|
||||
reg = CN23XX_SLI_PKT_CNT_INT;
|
||||
len += sprintf(s + len, "\n[%08x] (SLI_PKT_CNT_INT): %016llx\n", reg,
|
||||
(u64)octeon_read_csr64(oct, reg));
|
||||
|
||||
/*0x29140*/
|
||||
reg = CN23XX_SLI_PKT_TIME_INT;
|
||||
len += sprintf(s + len, "\n[%08x] (SLI_PKT_TIME_INT): %016llx\n", reg,
|
||||
(u64)octeon_read_csr64(oct, reg));
|
||||
|
||||
/*0x29160*/
|
||||
reg = 0x29160;
|
||||
len += sprintf(s + len, "\n[%08x] (SLI_PKT_INT): %016llx\n", reg,
|
||||
(u64)octeon_read_csr64(oct, reg));
|
||||
|
||||
/*0x29180*/
|
||||
reg = CN23XX_SLI_OQ_WMARK;
|
||||
len += sprintf(s + len, "\n[%08x] (SLI_PKT_OUTPUT_WMARK): %016llx\n",
|
||||
reg, (u64)octeon_read_csr64(oct, reg));
|
||||
|
||||
/*0x291E0*/
|
||||
reg = CN23XX_SLI_PKT_IOQ_RING_RST;
|
||||
len += sprintf(s + len, "\n[%08x] (SLI_PKT_RING_RST): %016llx\n", reg,
|
||||
(u64)octeon_read_csr64(oct, reg));
|
||||
|
||||
/*0x29210*/
|
||||
reg = CN23XX_SLI_GBL_CONTROL;
|
||||
len += sprintf(s + len,
|
||||
"\n[%08x] (SLI_PKT_GBL_CONTROL): %016llx\n", reg,
|
||||
(u64)octeon_read_csr64(oct, reg));
|
||||
|
||||
/*0x29220*/
|
||||
reg = 0x29220;
|
||||
len += sprintf(s + len, "\n[%08x] (SLI_PKT_BIST_STATUS): %016llx\n",
|
||||
reg, (u64)octeon_read_csr64(oct, reg));
|
||||
|
||||
/*PF only*/
|
||||
if (pf_num == 0) {
|
||||
/*0x29260*/
|
||||
reg = CN23XX_SLI_OUT_BP_EN_W1S;
|
||||
len += sprintf(s + len,
|
||||
"\n[%08x] (SLI_PKT_OUT_BP_EN_W1S): %016llx\n",
|
||||
reg, (u64)octeon_read_csr64(oct, reg));
|
||||
} else if (pf_num == 1) {
|
||||
/*0x29270*/
|
||||
reg = CN23XX_SLI_OUT_BP_EN2_W1S;
|
||||
len += sprintf(s + len,
|
||||
"\n[%08x] (SLI_PKT_OUT_BP_EN2_W1S): %016llx\n",
|
||||
reg, (u64)octeon_read_csr64(oct, reg));
|
||||
}
|
||||
|
||||
for (i = 0; i < CN23XX_MAX_OUTPUT_QUEUES; i++) {
|
||||
reg = CN23XX_SLI_OQ_BUFF_INFO_SIZE(i);
|
||||
len +=
|
||||
sprintf(s + len, "\n[%08x] (SLI_PKT%d_OUT_SIZE): %016llx\n",
|
||||
reg, i, (u64)octeon_read_csr64(oct, reg));
|
||||
}
|
||||
|
||||
/*0x10040*/
|
||||
for (i = 0; i < CN23XX_MAX_INPUT_QUEUES; i++) {
|
||||
reg = CN23XX_SLI_IQ_INSTR_COUNT64(i);
|
||||
len += sprintf(s + len,
|
||||
"\n[%08x] (SLI_PKT_IN_DONE%d_CNTS): %016llx\n",
|
||||
reg, i, (u64)octeon_read_csr64(oct, reg));
|
||||
}
|
||||
|
||||
/*0x10080*/
|
||||
for (i = 0; i < CN23XX_MAX_OUTPUT_QUEUES; i++) {
|
||||
reg = CN23XX_SLI_OQ_PKTS_CREDIT(i);
|
||||
len += sprintf(s + len,
|
||||
"\n[%08x] (SLI_PKT%d_SLIST_BAOFF_DBELL): %016llx\n",
|
||||
reg, i, (u64)octeon_read_csr64(oct, reg));
|
||||
}
|
||||
|
||||
/*0x10090*/
|
||||
for (i = 0; i < CN23XX_MAX_OUTPUT_QUEUES; i++) {
|
||||
reg = CN23XX_SLI_OQ_SIZE(i);
|
||||
len += sprintf(
|
||||
s + len, "\n[%08x] (SLI_PKT%d_SLIST_FIFO_RSIZE): %016llx\n",
|
||||
reg, i, (u64)octeon_read_csr64(oct, reg));
|
||||
}
|
||||
|
||||
/*0x10050*/
|
||||
for (i = 0; i < CN23XX_MAX_OUTPUT_QUEUES; i++) {
|
||||
reg = CN23XX_SLI_OQ_PKT_CONTROL(i);
|
||||
len += sprintf(
|
||||
s + len,
|
||||
"\n[%08x] (SLI_PKT%d__OUTPUT_CONTROL): %016llx\n",
|
||||
reg, i, (u64)octeon_read_csr64(oct, reg));
|
||||
}
|
||||
|
||||
/*0x10070*/
|
||||
for (i = 0; i < CN23XX_MAX_OUTPUT_QUEUES; i++) {
|
||||
reg = CN23XX_SLI_OQ_BASE_ADDR64(i);
|
||||
len += sprintf(s + len,
|
||||
"\n[%08x] (SLI_PKT%d_SLIST_BADDR): %016llx\n",
|
||||
reg, i, (u64)octeon_read_csr64(oct, reg));
|
||||
}
|
||||
|
||||
/*0x100a0*/
|
||||
for (i = 0; i < CN23XX_MAX_OUTPUT_QUEUES; i++) {
|
||||
reg = CN23XX_SLI_OQ_PKT_INT_LEVELS(i);
|
||||
len += sprintf(s + len,
|
||||
"\n[%08x] (SLI_PKT%d_INT_LEVELS): %016llx\n",
|
||||
reg, i, (u64)octeon_read_csr64(oct, reg));
|
||||
}
|
||||
|
||||
/*0x100b0*/
|
||||
for (i = 0; i < CN23XX_MAX_OUTPUT_QUEUES; i++) {
|
||||
reg = CN23XX_SLI_OQ_PKTS_SENT(i);
|
||||
len += sprintf(s + len, "\n[%08x] (SLI_PKT%d_CNTS): %016llx\n",
|
||||
reg, i, (u64)octeon_read_csr64(oct, reg));
|
||||
}
|
||||
|
||||
/*0x100c0*/
|
||||
for (i = 0; i < CN23XX_MAX_OUTPUT_QUEUES; i++) {
|
||||
reg = 0x100c0 + i * CN23XX_OQ_OFFSET;
|
||||
len += sprintf(s + len,
|
||||
"\n[%08x] (SLI_PKT%d_ERROR_INFO): %016llx\n",
|
||||
reg, i, (u64)octeon_read_csr64(oct, reg));
|
||||
|
||||
/*0x10000*/
|
||||
for (i = 0; i < CN23XX_MAX_INPUT_QUEUES; i++) {
|
||||
reg = CN23XX_SLI_IQ_PKT_CONTROL64(i);
|
||||
len += sprintf(
|
||||
s + len,
|
||||
"\n[%08x] (SLI_PKT%d_INPUT_CONTROL): %016llx\n",
|
||||
reg, i, (u64)octeon_read_csr64(oct, reg));
|
||||
}
|
||||
|
||||
/*0x10010*/
|
||||
for (i = 0; i < CN23XX_MAX_INPUT_QUEUES; i++) {
|
||||
reg = CN23XX_SLI_IQ_BASE_ADDR64(i);
|
||||
len += sprintf(
|
||||
s + len,
|
||||
"\n[%08x] (SLI_PKT%d_INSTR_BADDR): %016llx\n", reg,
|
||||
i, (u64)octeon_read_csr64(oct, reg));
|
||||
}
|
||||
|
||||
/*0x10020*/
|
||||
for (i = 0; i < CN23XX_MAX_INPUT_QUEUES; i++) {
|
||||
reg = CN23XX_SLI_IQ_DOORBELL(i);
|
||||
len += sprintf(
|
||||
s + len,
|
||||
"\n[%08x] (SLI_PKT%d_INSTR_BAOFF_DBELL): %016llx\n",
|
||||
reg, i, (u64)octeon_read_csr64(oct, reg));
|
||||
}
|
||||
|
||||
/*0x10030*/
|
||||
for (i = 0; i < CN23XX_MAX_INPUT_QUEUES; i++) {
|
||||
reg = CN23XX_SLI_IQ_SIZE(i);
|
||||
len += sprintf(
|
||||
s + len,
|
||||
"\n[%08x] (SLI_PKT%d_INSTR_FIFO_RSIZE): %016llx\n",
|
||||
reg, i, (u64)octeon_read_csr64(oct, reg));
|
||||
}
|
||||
|
||||
/*0x10040*/
|
||||
for (i = 0; i < CN23XX_MAX_INPUT_QUEUES; i++)
|
||||
reg = CN23XX_SLI_IQ_INSTR_COUNT64(i);
|
||||
len += sprintf(s + len,
|
||||
"\n[%08x] (SLI_PKT_IN_DONE%d_CNTS): %016llx\n",
|
||||
reg, i, (u64)octeon_read_csr64(oct, reg));
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int cn6xxx_read_csr_reg(char *s, struct octeon_device *oct)
|
||||
|
@ -1686,6 +2160,10 @@ static void lio_get_regs(struct net_device *dev,
|
|||
regs->version = OCT_ETHTOOL_REGSVER;
|
||||
|
||||
switch (oct->chip_id) {
|
||||
case OCTEON_CN23XX_PF_VID:
|
||||
memset(regbuf, 0, OCT_ETHTOOL_REGDUMP_LEN_23XX);
|
||||
len += cn23xx_read_csr_reg(regbuf + len, oct);
|
||||
break;
|
||||
case OCTEON_CN68XX:
|
||||
case OCTEON_CN66XX:
|
||||
memset(regbuf, 0, OCT_ETHTOOL_REGDUMP_LEN);
|
||||
|
@ -1727,6 +2205,7 @@ static const struct ethtool_ops lio_ethtool_ops = {
|
|||
.get_strings = lio_get_strings,
|
||||
.get_ethtool_stats = lio_get_ethtool_stats,
|
||||
.get_pauseparam = lio_get_pauseparam,
|
||||
.set_pauseparam = lio_set_pauseparam,
|
||||
.get_regs_len = lio_get_regs_len,
|
||||
.get_regs = lio_get_regs,
|
||||
.get_msglevel = lio_get_msglevel,
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <linux/firmware.h>
|
||||
#include <linux/ptp_clock_kernel.h>
|
||||
#include <net/vxlan.h>
|
||||
#include <linux/kthread.h>
|
||||
#include "liquidio_common.h"
|
||||
#include "octeon_droq.h"
|
||||
#include "octeon_iq.h"
|
||||
|
@ -96,6 +97,14 @@ struct liquidio_if_cfg_resp {
|
|||
u64 status;
|
||||
};
|
||||
|
||||
struct liquidio_rx_ctl_context {
|
||||
int octeon_id;
|
||||
|
||||
wait_queue_head_t wc;
|
||||
|
||||
int cond;
|
||||
};
|
||||
|
||||
struct oct_link_status_resp {
|
||||
u64 rh;
|
||||
struct oct_link_info link_info;
|
||||
|
@ -856,6 +865,52 @@ static void print_link_info(struct net_device *netdev)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Routine to notify MTU change
|
||||
* @param work work_struct data structure
|
||||
*/
|
||||
static void octnet_link_status_change(struct work_struct *work)
|
||||
{
|
||||
struct cavium_wk *wk = (struct cavium_wk *)work;
|
||||
struct lio *lio = (struct lio *)wk->ctxptr;
|
||||
|
||||
rtnl_lock();
|
||||
call_netdevice_notifiers(NETDEV_CHANGEMTU, lio->netdev);
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Sets up the mtu status change work
|
||||
* @param netdev network device
|
||||
*/
|
||||
static inline int setup_link_status_change_wq(struct net_device *netdev)
|
||||
{
|
||||
struct lio *lio = GET_LIO(netdev);
|
||||
struct octeon_device *oct = lio->oct_dev;
|
||||
|
||||
lio->link_status_wq.wq = alloc_workqueue("link-status",
|
||||
WQ_MEM_RECLAIM, 0);
|
||||
if (!lio->link_status_wq.wq) {
|
||||
dev_err(&oct->pci_dev->dev, "unable to create cavium link status wq\n");
|
||||
return -1;
|
||||
}
|
||||
INIT_DELAYED_WORK(&lio->link_status_wq.wk.work,
|
||||
octnet_link_status_change);
|
||||
lio->link_status_wq.wk.ctxptr = lio;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void cleanup_link_status_change_wq(struct net_device *netdev)
|
||||
{
|
||||
struct lio *lio = GET_LIO(netdev);
|
||||
|
||||
if (lio->link_status_wq.wq) {
|
||||
cancel_delayed_work_sync(&lio->link_status_wq.wk.work);
|
||||
destroy_workqueue(lio->link_status_wq.wq);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Update link status
|
||||
* @param netdev network device
|
||||
|
@ -894,8 +949,6 @@ static void update_txq_status(struct octeon_device *oct, int iq_num)
|
|||
struct lio *lio;
|
||||
struct octeon_instr_queue *iq = oct->instr_queue[iq_num];
|
||||
|
||||
/*octeon_update_iq_read_idx(oct, iq);*/
|
||||
|
||||
netdev = oct->props[iq->ifidx].netdev;
|
||||
|
||||
/* This is needed because the first IQ does not have
|
||||
|
@ -948,8 +1001,7 @@ int liquidio_schedule_msix_droq_pkt_handler(struct octeon_droq *droq, u64 ret)
|
|||
* \brief Droq packet processor sceduler
|
||||
* @param oct octeon device
|
||||
*/
|
||||
static
|
||||
void liquidio_schedule_droq_pkt_handlers(struct octeon_device *oct)
|
||||
static void liquidio_schedule_droq_pkt_handlers(struct octeon_device *oct)
|
||||
{
|
||||
struct octeon_device_priv *oct_priv =
|
||||
(struct octeon_device_priv *)oct->priv;
|
||||
|
@ -1133,6 +1185,102 @@ static int octeon_setup_interrupt(struct octeon_device *oct)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int liquidio_watchdog(void *param)
|
||||
{
|
||||
u64 wdog;
|
||||
u16 mask_of_stuck_cores = 0;
|
||||
u16 mask_of_crashed_cores = 0;
|
||||
int core_num;
|
||||
u8 core_is_stuck[LIO_MAX_CORES];
|
||||
u8 core_crashed[LIO_MAX_CORES];
|
||||
struct octeon_device *oct = param;
|
||||
|
||||
memset(core_is_stuck, 0, sizeof(core_is_stuck));
|
||||
memset(core_crashed, 0, sizeof(core_crashed));
|
||||
|
||||
while (!kthread_should_stop()) {
|
||||
mask_of_crashed_cores =
|
||||
(u16)octeon_read_csr64(oct, CN23XX_SLI_SCRATCH2);
|
||||
|
||||
for (core_num = 0; core_num < LIO_MAX_CORES; core_num++) {
|
||||
if (!core_is_stuck[core_num]) {
|
||||
wdog = lio_pci_readq(oct, CIU3_WDOG(core_num));
|
||||
|
||||
/* look at watchdog state field */
|
||||
wdog &= CIU3_WDOG_MASK;
|
||||
if (wdog) {
|
||||
/* this watchdog timer has expired */
|
||||
core_is_stuck[core_num] =
|
||||
LIO_MONITOR_WDOG_EXPIRE;
|
||||
mask_of_stuck_cores |= (1 << core_num);
|
||||
}
|
||||
}
|
||||
|
||||
if (!core_crashed[core_num])
|
||||
core_crashed[core_num] =
|
||||
(mask_of_crashed_cores >> core_num) & 1;
|
||||
}
|
||||
|
||||
if (mask_of_stuck_cores) {
|
||||
for (core_num = 0; core_num < LIO_MAX_CORES;
|
||||
core_num++) {
|
||||
if (core_is_stuck[core_num] == 1) {
|
||||
dev_err(&oct->pci_dev->dev,
|
||||
"ERROR: Octeon core %d is stuck!\n",
|
||||
core_num);
|
||||
/* 2 means we have printk'd an error
|
||||
* so no need to repeat the same printk
|
||||
*/
|
||||
core_is_stuck[core_num] =
|
||||
LIO_MONITOR_CORE_STUCK_MSGD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mask_of_crashed_cores) {
|
||||
for (core_num = 0; core_num < LIO_MAX_CORES;
|
||||
core_num++) {
|
||||
if (core_crashed[core_num] == 1) {
|
||||
dev_err(&oct->pci_dev->dev,
|
||||
"ERROR: Octeon core %d crashed! See oct-fwdump for details.\n",
|
||||
core_num);
|
||||
/* 2 means we have printk'd an error
|
||||
* so no need to repeat the same printk
|
||||
*/
|
||||
core_crashed[core_num] =
|
||||
LIO_MONITOR_CORE_STUCK_MSGD;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_MODULE_UNLOAD
|
||||
if (mask_of_stuck_cores || mask_of_crashed_cores) {
|
||||
/* make module refcount=0 so that rmmod will work */
|
||||
long refcount;
|
||||
|
||||
refcount = module_refcount(THIS_MODULE);
|
||||
|
||||
while (refcount > 0) {
|
||||
module_put(THIS_MODULE);
|
||||
refcount = module_refcount(THIS_MODULE);
|
||||
}
|
||||
|
||||
/* compensate for and withstand an unlikely (but still
|
||||
* possible) race condition
|
||||
*/
|
||||
while (refcount < 0) {
|
||||
try_module_get(THIS_MODULE);
|
||||
refcount = module_refcount(THIS_MODULE);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* sleep for two seconds */
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(2 * HZ);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief PCI probe handler
|
||||
* @param pdev PCI device structure
|
||||
|
@ -1178,6 +1326,30 @@ liquidio_probe(struct pci_dev *pdev,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (OCTEON_CN23XX_PF(oct_dev)) {
|
||||
u64 scratch1;
|
||||
u8 bus, device, function;
|
||||
|
||||
scratch1 = octeon_read_csr64(oct_dev, CN23XX_SLI_SCRATCH1);
|
||||
if (!(scratch1 & 4ULL)) {
|
||||
/* Bit 2 of SLI_SCRATCH_1 is a flag that indicates that
|
||||
* the lio watchdog kernel thread is running for this
|
||||
* NIC. Each NIC gets one watchdog kernel thread.
|
||||
*/
|
||||
scratch1 |= 4ULL;
|
||||
octeon_write_csr64(oct_dev, CN23XX_SLI_SCRATCH1,
|
||||
scratch1);
|
||||
|
||||
bus = pdev->bus->number;
|
||||
device = PCI_SLOT(pdev->devfn);
|
||||
function = PCI_FUNC(pdev->devfn);
|
||||
oct_dev->watchdog_task = kthread_create(
|
||||
liquidio_watchdog, oct_dev,
|
||||
"liowd/%02hhx:%02hhx.%hhx", bus, device, function);
|
||||
wake_up_process(oct_dev->watchdog_task);
|
||||
}
|
||||
}
|
||||
|
||||
oct_dev->rx_pause = 1;
|
||||
oct_dev->tx_pause = 1;
|
||||
|
||||
|
@ -1293,17 +1465,16 @@ static void octeon_destroy_resources(struct octeon_device *oct)
|
|||
case OCT_DEV_RESP_LIST_INIT_DONE:
|
||||
octeon_delete_response_list(oct);
|
||||
|
||||
/* fallthrough */
|
||||
case OCT_DEV_SC_BUFF_POOL_INIT_DONE:
|
||||
octeon_free_sc_buffer_pool(oct);
|
||||
|
||||
/* fallthrough */
|
||||
case OCT_DEV_INSTR_QUEUE_INIT_DONE:
|
||||
for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) {
|
||||
if (!(oct->io_qmask.iq & (1ULL << i)))
|
||||
if (!(oct->io_qmask.iq & BIT_ULL(i)))
|
||||
continue;
|
||||
octeon_delete_instr_queue(oct, i);
|
||||
}
|
||||
/* fallthrough */
|
||||
case OCT_DEV_SC_BUFF_POOL_INIT_DONE:
|
||||
octeon_free_sc_buffer_pool(oct);
|
||||
|
||||
/* fallthrough */
|
||||
case OCT_DEV_DISPATCH_INIT_DONE:
|
||||
|
@ -1331,6 +1502,34 @@ static void octeon_destroy_resources(struct octeon_device *oct)
|
|||
tasklet_kill(&oct_priv->droq_tasklet);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Callback for rx ctrl
|
||||
* @param status status of request
|
||||
* @param buf pointer to resp structure
|
||||
*/
|
||||
static void rx_ctl_callback(struct octeon_device *oct,
|
||||
u32 status,
|
||||
void *buf)
|
||||
{
|
||||
struct octeon_soft_command *sc = (struct octeon_soft_command *)buf;
|
||||
struct liquidio_rx_ctl_context *ctx;
|
||||
|
||||
ctx = (struct liquidio_rx_ctl_context *)sc->ctxptr;
|
||||
|
||||
oct = lio_get_device(ctx->octeon_id);
|
||||
if (status)
|
||||
dev_err(&oct->pci_dev->dev, "rx ctl instruction failed. Status: %llx\n",
|
||||
CVM_CAST64(status));
|
||||
WRITE_ONCE(ctx->cond, 1);
|
||||
|
||||
/* This barrier is required to be sure that the response has been
|
||||
* written fully before waking up the handler
|
||||
*/
|
||||
wmb();
|
||||
|
||||
wake_up_interruptible(&ctx->wc);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Send Rx control command
|
||||
* @param lio per-network private data
|
||||
|
@ -1338,17 +1537,55 @@ static void octeon_destroy_resources(struct octeon_device *oct)
|
|||
*/
|
||||
static void send_rx_ctrl_cmd(struct lio *lio, int start_stop)
|
||||
{
|
||||
struct octnic_ctrl_pkt nctrl;
|
||||
struct octeon_soft_command *sc;
|
||||
struct liquidio_rx_ctl_context *ctx;
|
||||
union octnet_cmd *ncmd;
|
||||
int ctx_size = sizeof(struct liquidio_rx_ctl_context);
|
||||
struct octeon_device *oct = (struct octeon_device *)lio->oct_dev;
|
||||
int retval;
|
||||
|
||||
memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
|
||||
if (oct->props[lio->ifidx].rx_on == start_stop)
|
||||
return;
|
||||
|
||||
nctrl.ncmd.s.cmd = OCTNET_CMD_RX_CTL;
|
||||
nctrl.ncmd.s.param1 = start_stop;
|
||||
nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
|
||||
nctrl.netpndev = (u64)lio->netdev;
|
||||
sc = (struct octeon_soft_command *)
|
||||
octeon_alloc_soft_command(oct, OCTNET_CMD_SIZE,
|
||||
16, ctx_size);
|
||||
|
||||
if (octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl) < 0)
|
||||
ncmd = (union octnet_cmd *)sc->virtdptr;
|
||||
ctx = (struct liquidio_rx_ctl_context *)sc->ctxptr;
|
||||
|
||||
WRITE_ONCE(ctx->cond, 0);
|
||||
ctx->octeon_id = lio_get_device_id(oct);
|
||||
init_waitqueue_head(&ctx->wc);
|
||||
|
||||
ncmd->u64 = 0;
|
||||
ncmd->s.cmd = OCTNET_CMD_RX_CTL;
|
||||
ncmd->s.param1 = start_stop;
|
||||
|
||||
octeon_swap_8B_data((u64 *)ncmd, (OCTNET_CMD_SIZE >> 3));
|
||||
|
||||
sc->iq_no = lio->linfo.txpciq[0].s.q_no;
|
||||
|
||||
octeon_prepare_soft_command(oct, sc, OPCODE_NIC,
|
||||
OPCODE_NIC_CMD, 0, 0, 0);
|
||||
|
||||
sc->callback = rx_ctl_callback;
|
||||
sc->callback_arg = sc;
|
||||
sc->wait_time = 5000;
|
||||
|
||||
retval = octeon_send_soft_command(oct, sc);
|
||||
if (retval == IQ_SEND_FAILED) {
|
||||
netif_info(lio, rx_err, lio->netdev, "Failed to send RX Control message\n");
|
||||
} else {
|
||||
/* Sleep on a wait queue till the cond flag indicates that the
|
||||
* response arrived or timed-out.
|
||||
*/
|
||||
if (sleep_cond(&ctx->wc, &ctx->cond) == -EINTR)
|
||||
return;
|
||||
oct->props[lio->ifidx].rx_on = start_stop;
|
||||
}
|
||||
|
||||
octeon_free_soft_command(oct, sc);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1375,21 +1612,24 @@ static void liquidio_destroy_nic_device(struct octeon_device *oct, int ifidx)
|
|||
|
||||
dev_dbg(&oct->pci_dev->dev, "NIC device cleanup\n");
|
||||
|
||||
send_rx_ctrl_cmd(lio, 0);
|
||||
|
||||
if (atomic_read(&lio->ifstate) & LIO_IFSTATE_RUNNING)
|
||||
txqs_stop(netdev);
|
||||
liquidio_stop(netdev);
|
||||
|
||||
if (oct->props[lio->ifidx].napi_enabled == 1) {
|
||||
list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list)
|
||||
napi_disable(napi);
|
||||
|
||||
oct->props[lio->ifidx].napi_enabled = 0;
|
||||
|
||||
if (OCTEON_CN23XX_PF(oct))
|
||||
oct->droq[0]->ops.poll_mode = 0;
|
||||
}
|
||||
|
||||
if (atomic_read(&lio->ifstate) & LIO_IFSTATE_REGISTERED)
|
||||
unregister_netdev(netdev);
|
||||
|
||||
cleanup_link_status_change_wq(netdev);
|
||||
|
||||
delete_glists(lio);
|
||||
|
||||
free_netdev(netdev);
|
||||
|
@ -1442,6 +1682,9 @@ static void liquidio_remove(struct pci_dev *pdev)
|
|||
|
||||
dev_dbg(&oct_dev->pci_dev->dev, "Stopping device\n");
|
||||
|
||||
if (oct_dev->watchdog_task)
|
||||
kthread_stop(oct_dev->watchdog_task);
|
||||
|
||||
if (oct_dev->app_mode && (oct_dev->app_mode == CVM_DRV_NIC_APP))
|
||||
liquidio_stop_nic_module(oct_dev);
|
||||
|
||||
|
@ -1941,7 +2184,7 @@ static void if_cfg_callback(struct octeon_device *oct,
|
|||
struct liquidio_if_cfg_context *ctx;
|
||||
|
||||
resp = (struct liquidio_if_cfg_resp *)sc->virtrptr;
|
||||
ctx = (struct liquidio_if_cfg_context *)sc->ctxptr;
|
||||
ctx = (struct liquidio_if_cfg_context *)sc->ctxptr;
|
||||
|
||||
oct = lio_get_device(ctx->octeon_id);
|
||||
if (resp->status)
|
||||
|
@ -2134,11 +2377,14 @@ static void napi_schedule_wrapper(void *param)
|
|||
*/
|
||||
static void liquidio_napi_drv_callback(void *arg)
|
||||
{
|
||||
struct octeon_device *oct;
|
||||
struct octeon_droq *droq = arg;
|
||||
int this_cpu = smp_processor_id();
|
||||
|
||||
if (droq->cpu_id == this_cpu) {
|
||||
napi_schedule(&droq->napi);
|
||||
oct = droq->oct_dev;
|
||||
|
||||
if (OCTEON_CN23XX_PF(oct) || droq->cpu_id == this_cpu) {
|
||||
napi_schedule_irqoff(&droq->napi);
|
||||
} else {
|
||||
struct call_single_data *csd = &droq->csd;
|
||||
|
||||
|
@ -2267,6 +2513,14 @@ static inline int setup_io_queues(struct octeon_device *octeon_dev,
|
|||
octeon_register_droq_ops(octeon_dev, q_no, &droq_ops);
|
||||
}
|
||||
|
||||
if (OCTEON_CN23XX_PF(octeon_dev)) {
|
||||
/* 23XX PF can receive control messages (via the first PF-owned
|
||||
* droq) from the firmware even if the ethX interface is down,
|
||||
* so that's why poll_mode must be off for the first droq.
|
||||
*/
|
||||
octeon_dev->droq[0]->ops.poll_mode = 0;
|
||||
}
|
||||
|
||||
/* set up IQs. */
|
||||
for (q = 0; q < lio->linfo.num_txpciq; q++) {
|
||||
num_tx_descs = CFG_GET_NUM_TX_DESCS_NIC_IF(octeon_get_conf
|
||||
|
@ -2351,12 +2605,20 @@ static int liquidio_open(struct net_device *netdev)
|
|||
napi_enable(napi);
|
||||
|
||||
oct->props[lio->ifidx].napi_enabled = 1;
|
||||
|
||||
if (OCTEON_CN23XX_PF(oct))
|
||||
oct->droq[0]->ops.poll_mode = 1;
|
||||
}
|
||||
|
||||
oct_ptp_open(netdev);
|
||||
|
||||
ifstate_set(lio, LIO_IFSTATE_RUNNING);
|
||||
|
||||
/* Ready for link status updates */
|
||||
lio->intf_open = 1;
|
||||
|
||||
netif_info(lio, ifup, lio->netdev, "Interface Open, ready for traffic\n");
|
||||
|
||||
if (OCTEON_CN23XX_PF(oct)) {
|
||||
if (!oct->msix_on)
|
||||
if (setup_tx_poll_fn(netdev))
|
||||
|
@ -2368,14 +2630,9 @@ static int liquidio_open(struct net_device *netdev)
|
|||
|
||||
start_txq(netdev);
|
||||
|
||||
netif_info(lio, ifup, lio->netdev, "Interface Open, ready for traffic\n");
|
||||
|
||||
/* tell Octeon to start forwarding packets to host */
|
||||
send_rx_ctrl_cmd(lio, 1);
|
||||
|
||||
/* Ready for link status updates */
|
||||
lio->intf_open = 1;
|
||||
|
||||
dev_info(&oct->pci_dev->dev, "%s interface is opened\n",
|
||||
netdev->name);
|
||||
|
||||
|
@ -2795,9 +3052,15 @@ static inline int send_nic_timestamp_pkt(struct octeon_device *oct,
|
|||
sc->callback_arg = finfo->skb;
|
||||
sc->iq_no = ndata->q_no;
|
||||
|
||||
len = (u32)((struct octeon_instr_ih2 *)(&sc->cmd.cmd2.ih2))->dlengsz;
|
||||
if (OCTEON_CN23XX_PF(oct))
|
||||
len = (u32)((struct octeon_instr_ih3 *)
|
||||
(&sc->cmd.cmd3.ih3))->dlengsz;
|
||||
else
|
||||
len = (u32)((struct octeon_instr_ih2 *)
|
||||
(&sc->cmd.cmd2.ih2))->dlengsz;
|
||||
|
||||
ring_doorbell = 1;
|
||||
|
||||
retval = octeon_send_command(oct, sc->iq_no, ring_doorbell, &sc->cmd,
|
||||
sc, len, ndata->reqtype);
|
||||
|
||||
|
@ -2929,7 +3192,10 @@ static int liquidio_xmit(struct sk_buff *skb, struct net_device *netdev)
|
|||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
||||
ndata.cmd.cmd2.dptr = dptr;
|
||||
if (OCTEON_CN23XX_PF(oct))
|
||||
ndata.cmd.cmd3.dptr = dptr;
|
||||
else
|
||||
ndata.cmd.cmd2.dptr = dptr;
|
||||
finfo->dptr = dptr;
|
||||
ndata.reqtype = REQTYPE_NORESP_NET;
|
||||
|
||||
|
@ -3004,15 +3270,23 @@ static int liquidio_xmit(struct sk_buff *skb, struct net_device *netdev)
|
|||
g->sg_size, DMA_TO_DEVICE);
|
||||
dptr = g->sg_dma_ptr;
|
||||
|
||||
ndata.cmd.cmd2.dptr = dptr;
|
||||
if (OCTEON_CN23XX_PF(oct))
|
||||
ndata.cmd.cmd3.dptr = dptr;
|
||||
else
|
||||
ndata.cmd.cmd2.dptr = dptr;
|
||||
finfo->dptr = dptr;
|
||||
finfo->g = g;
|
||||
|
||||
ndata.reqtype = REQTYPE_NORESP_NET_SG;
|
||||
}
|
||||
|
||||
irh = (struct octeon_instr_irh *)&ndata.cmd.cmd2.irh;
|
||||
tx_info = (union tx_info *)&ndata.cmd.cmd2.ossp[0];
|
||||
if (OCTEON_CN23XX_PF(oct)) {
|
||||
irh = (struct octeon_instr_irh *)&ndata.cmd.cmd3.irh;
|
||||
tx_info = (union tx_info *)&ndata.cmd.cmd3.ossp[0];
|
||||
} else {
|
||||
irh = (struct octeon_instr_irh *)&ndata.cmd.cmd2.irh;
|
||||
tx_info = (union tx_info *)&ndata.cmd.cmd2.ossp[0];
|
||||
}
|
||||
|
||||
if (skb_shinfo(skb)->gso_size) {
|
||||
tx_info->s.gso_size = skb_shinfo(skb)->gso_size;
|
||||
|
@ -3505,7 +3779,11 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
|
|||
/* Sleep on a wait queue till the cond flag indicates that the
|
||||
* response arrived or timed-out.
|
||||
*/
|
||||
sleep_cond(&ctx->wc, &ctx->cond);
|
||||
if (sleep_cond(&ctx->wc, &ctx->cond) == -EINTR) {
|
||||
dev_err(&octeon_dev->pci_dev->dev, "Wait interrupted\n");
|
||||
goto setup_nic_wait_intr;
|
||||
}
|
||||
|
||||
retval = resp->status;
|
||||
if (retval) {
|
||||
dev_err(&octeon_dev->pci_dev->dev, "iq/oq config failed\n");
|
||||
|
@ -3656,7 +3934,10 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
|
|||
|
||||
/* Register ethtool support */
|
||||
liquidio_set_ethtool_ops(netdev);
|
||||
octeon_dev->priv_flags = 0x0;
|
||||
if (lio->oct_dev->chip_id == OCTEON_CN23XX_PF_VID)
|
||||
octeon_dev->priv_flags = OCT_PRIV_FLAG_DEFAULT;
|
||||
else
|
||||
octeon_dev->priv_flags = 0x0;
|
||||
|
||||
if (netdev->features & NETIF_F_LRO)
|
||||
liquidio_set_feature(netdev, OCTNET_CMD_LRO_ENABLE,
|
||||
|
@ -3668,6 +3949,9 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
|
|||
liquidio_set_feature(netdev,
|
||||
OCTNET_CMD_VERBOSE_ENABLE, 0);
|
||||
|
||||
if (setup_link_status_change_wq(netdev))
|
||||
goto setup_nic_dev_fail;
|
||||
|
||||
/* Register the network device with the OS */
|
||||
if (register_netdev(netdev)) {
|
||||
dev_err(&octeon_dev->pci_dev->dev, "Device registration failed\n");
|
||||
|
@ -3703,6 +3987,8 @@ setup_nic_dev_fail:
|
|||
|
||||
octeon_free_soft_command(octeon_dev, sc);
|
||||
|
||||
setup_nic_wait_intr:
|
||||
|
||||
while (i--) {
|
||||
dev_err(&octeon_dev->pci_dev->dev,
|
||||
"NIC ifidx:%d Setup failed\n", i);
|
||||
|
@ -3732,8 +4018,7 @@ static int liquidio_init_nic_module(struct octeon_device *oct)
|
|||
/* run port_config command for each port */
|
||||
oct->ifcount = num_nic_ports;
|
||||
|
||||
memset(oct->props, 0,
|
||||
sizeof(struct octdev_props) * num_nic_ports);
|
||||
memset(oct->props, 0, sizeof(struct octdev_props) * num_nic_ports);
|
||||
|
||||
for (i = 0; i < MAX_OCTEON_LINKS; i++)
|
||||
oct->props[i].gmxport = -1;
|
||||
|
@ -3749,7 +4034,7 @@ static int liquidio_init_nic_module(struct octeon_device *oct)
|
|||
/* Initialize interrupt moderation params */
|
||||
intrmod_cfg = &((struct octeon_device *)oct)->intrmod;
|
||||
intrmod_cfg->rx_enable = 1;
|
||||
intrmod_cfg->check_intrvl = LIO_INTRMOD_CHECK_INTERVAL;
|
||||
intrmod_cfg->check_intrvl = LIO_INTRMOD_CHECK_INTERVAL;
|
||||
intrmod_cfg->maxpkt_ratethr = LIO_INTRMOD_MAXPKT_RATETHR;
|
||||
intrmod_cfg->minpkt_ratethr = LIO_INTRMOD_MINPKT_RATETHR;
|
||||
intrmod_cfg->rx_maxcnt_trigger = LIO_INTRMOD_RXMAXCNT_TRIGGER;
|
||||
|
@ -3761,6 +4046,7 @@ static int liquidio_init_nic_module(struct octeon_device *oct)
|
|||
intrmod_cfg->tx_mincnt_trigger = LIO_INTRMOD_TXMINCNT_TRIGGER;
|
||||
intrmod_cfg->rx_frames = CFG_GET_OQ_INTR_PKT(octeon_get_conf(oct));
|
||||
intrmod_cfg->rx_usecs = CFG_GET_OQ_INTR_TIME(octeon_get_conf(oct));
|
||||
intrmod_cfg->tx_frames = CFG_GET_IQ_INTR_PKT(octeon_get_conf(oct));
|
||||
dev_dbg(&oct->pci_dev->dev, "Network interfaces ready\n");
|
||||
|
||||
return retval;
|
||||
|
|
|
@ -232,6 +232,9 @@ static inline void add_sg_size(struct octeon_sg_entry *sg_entry,
|
|||
#define OCTNET_CMD_ADD_VLAN_FILTER 0x17
|
||||
#define OCTNET_CMD_DEL_VLAN_FILTER 0x18
|
||||
#define OCTNET_CMD_VXLAN_PORT_CONFIG 0x19
|
||||
|
||||
#define OCTNET_CMD_ID_ACTIVE 0x1a
|
||||
|
||||
#define OCTNET_CMD_VXLAN_PORT_ADD 0x0
|
||||
#define OCTNET_CMD_VXLAN_PORT_DEL 0x1
|
||||
#define OCTNET_CMD_RXCSUM_ENABLE 0x0
|
||||
|
@ -310,6 +313,13 @@ union octnet_cmd {
|
|||
|
||||
#define OCTNET_CMD_SIZE (sizeof(union octnet_cmd))
|
||||
|
||||
/*pkiih3 + irh + ossp[0] + ossp[1] + rdp + rptr = 40 bytes */
|
||||
#define LIO_SOFTCMDRESP_IH2 40
|
||||
#define LIO_SOFTCMDRESP_IH3 (40 + 8)
|
||||
|
||||
#define LIO_PCICMD_O2 24
|
||||
#define LIO_PCICMD_O3 (24 + 8)
|
||||
|
||||
/* Instruction Header(DPI) - for OCTEON-III models */
|
||||
struct octeon_instr_ih3 {
|
||||
#ifdef __BIG_ENDIAN_BITFIELD
|
||||
|
@ -828,6 +838,8 @@ struct oct_link_stats {
|
|||
#define VITESSE_PHY_GPIO_DRIVEOFF 0x4
|
||||
#define VITESSE_PHY_GPIO_HIGH 0x2
|
||||
#define VITESSE_PHY_GPIO_LOW 0x3
|
||||
#define LED_IDENTIFICATION_ON 0x1
|
||||
#define LED_IDENTIFICATION_OFF 0x0
|
||||
|
||||
struct oct_mdio_cmd {
|
||||
u64 op;
|
||||
|
|
|
@ -793,7 +793,6 @@ int octeon_setup_instr_queues(struct octeon_device *oct)
|
|||
union oct_txpciq txpciq;
|
||||
int numa_node = cpu_to_node(iq_no % num_online_cpus());
|
||||
|
||||
/* this causes queue 0 to be default queue */
|
||||
if (OCTEON_CN6XXX(oct))
|
||||
num_descs =
|
||||
CFG_GET_NUM_DEF_TX_DESCS(CHIP_FIELD(oct, cn6xxx, conf));
|
||||
|
@ -816,6 +815,7 @@ int octeon_setup_instr_queues(struct octeon_device *oct)
|
|||
oct->instr_queue[0]->ifidx = 0;
|
||||
txpciq.u64 = 0;
|
||||
txpciq.s.q_no = iq_no;
|
||||
txpciq.s.pkind = oct->pfvf_hsword.pkind;
|
||||
txpciq.s.use_qpg = 0;
|
||||
txpciq.s.qpg = 0;
|
||||
if (octeon_init_instr_queue(oct, txpciq, num_descs)) {
|
||||
|
@ -835,7 +835,6 @@ int octeon_setup_output_queues(struct octeon_device *oct)
|
|||
u32 oq_no = 0;
|
||||
int numa_node = cpu_to_node(oq_no % num_online_cpus());
|
||||
|
||||
/* this causes queue 0 to be default queue */
|
||||
if (OCTEON_CN6XXX(oct)) {
|
||||
num_descs =
|
||||
CFG_GET_NUM_DEF_RX_DESCS(CHIP_FIELD(oct, cn6xxx, conf));
|
||||
|
@ -863,10 +862,10 @@ int octeon_setup_output_queues(struct octeon_device *oct)
|
|||
|
||||
void octeon_set_io_queues_off(struct octeon_device *oct)
|
||||
{
|
||||
/* Disable the i/p and o/p queues for this Octeon. */
|
||||
|
||||
octeon_write_csr(oct, CN6XXX_SLI_PKT_INSTR_ENB, 0);
|
||||
octeon_write_csr(oct, CN6XXX_SLI_PKT_OUT_ENB, 0);
|
||||
if (OCTEON_CN6XXX(oct)) {
|
||||
octeon_write_csr(oct, CN6XXX_SLI_PKT_INSTR_ENB, 0);
|
||||
octeon_write_csr(oct, CN6XXX_SLI_PKT_OUT_ENB, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void octeon_set_droq_pkt_op(struct octeon_device *oct,
|
||||
|
@ -876,14 +875,16 @@ void octeon_set_droq_pkt_op(struct octeon_device *oct,
|
|||
u32 reg_val = 0;
|
||||
|
||||
/* Disable the i/p and o/p queues for this Octeon. */
|
||||
reg_val = octeon_read_csr(oct, CN6XXX_SLI_PKT_OUT_ENB);
|
||||
if (OCTEON_CN6XXX(oct)) {
|
||||
reg_val = octeon_read_csr(oct, CN6XXX_SLI_PKT_OUT_ENB);
|
||||
|
||||
if (enable)
|
||||
reg_val = reg_val | (1 << q_no);
|
||||
else
|
||||
reg_val = reg_val & (~(1 << q_no));
|
||||
if (enable)
|
||||
reg_val = reg_val | (1 << q_no);
|
||||
else
|
||||
reg_val = reg_val & (~(1 << q_no));
|
||||
|
||||
octeon_write_csr(oct, CN6XXX_SLI_PKT_OUT_ENB, reg_val);
|
||||
octeon_write_csr(oct, CN6XXX_SLI_PKT_OUT_ENB, reg_val);
|
||||
}
|
||||
}
|
||||
|
||||
int octeon_init_dispatch_list(struct octeon_device *oct)
|
||||
|
@ -1100,6 +1101,12 @@ int octeon_core_drv_init(struct octeon_recv_info *recv_info, void *buf)
|
|||
}
|
||||
oct->fw_info.app_cap_flags = recv_pkt->rh.r_core_drv_init.app_cap_flags;
|
||||
oct->fw_info.app_mode = (u32)recv_pkt->rh.r_core_drv_init.app_mode;
|
||||
oct->pfvf_hsword.app_mode = (u32)recv_pkt->rh.r_core_drv_init.app_mode;
|
||||
|
||||
oct->pfvf_hsword.pkind = recv_pkt->rh.r_core_drv_init.pkind;
|
||||
|
||||
for (i = 0; i < oct->num_iqs; i++)
|
||||
oct->instr_queue[i]->txpciq.s.pkind = oct->pfvf_hsword.pkind;
|
||||
|
||||
atomic_set(&oct->status, OCT_DEV_CORE_OK);
|
||||
|
||||
|
@ -1294,17 +1301,36 @@ int lio_get_device_id(void *dev)
|
|||
|
||||
void lio_enable_irq(struct octeon_droq *droq, struct octeon_instr_queue *iq)
|
||||
{
|
||||
u64 instr_cnt;
|
||||
struct octeon_device *oct = NULL;
|
||||
|
||||
/* the whole thing needs to be atomic, ideally */
|
||||
if (droq) {
|
||||
spin_lock_bh(&droq->lock);
|
||||
writel(droq->pkt_count, droq->pkts_sent_reg);
|
||||
droq->pkt_count = 0;
|
||||
spin_unlock_bh(&droq->lock);
|
||||
oct = droq->oct_dev;
|
||||
}
|
||||
if (iq) {
|
||||
spin_lock_bh(&iq->lock);
|
||||
writel(iq->pkt_in_done, iq->inst_cnt_reg);
|
||||
iq->pkt_in_done = 0;
|
||||
spin_unlock_bh(&iq->lock);
|
||||
oct = iq->oct_dev;
|
||||
}
|
||||
/*write resend. Writing RESEND in SLI_PKTX_CNTS should be enough
|
||||
*to trigger tx interrupts as well, if they are pending.
|
||||
*/
|
||||
if (oct && OCTEON_CN23XX_PF(oct)) {
|
||||
if (droq)
|
||||
writeq(CN23XX_INTR_RESEND, droq->pkts_sent_reg);
|
||||
/*we race with firmrware here. read and write the IN_DONE_CNTS*/
|
||||
else if (iq) {
|
||||
instr_cnt = readq(iq->inst_cnt_reg);
|
||||
writeq(((instr_cnt & 0xFFFFFFFF00000000ULL) |
|
||||
CN23XX_INTR_RESEND),
|
||||
iq->inst_cnt_reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -275,6 +275,7 @@ struct octdev_props {
|
|||
/* Each interface in the Octeon device has a network
|
||||
* device pointer (used for OS specific calls).
|
||||
*/
|
||||
int rx_on;
|
||||
int napi_enabled;
|
||||
int gmxport;
|
||||
struct net_device *netdev;
|
||||
|
@ -483,6 +484,8 @@ struct octeon_device {
|
|||
|
||||
/* private flags to control driver-specific features through ethtool */
|
||||
u32 priv_flags;
|
||||
|
||||
void *watchdog_task;
|
||||
};
|
||||
|
||||
#define OCT_DRV_ONLINE 1
|
||||
|
@ -752,8 +755,15 @@ enum {
|
|||
OCT_PRIV_FLAG_TX_BYTES = 0, /* Tx interrupts by pending byte count */
|
||||
};
|
||||
|
||||
static inline void lio_set_priv_flag(struct octeon_device *octdev, u32 flag,
|
||||
u32 val)
|
||||
#define OCT_PRIV_FLAG_DEFAULT 0x0
|
||||
|
||||
static inline u32 lio_get_priv_flag(struct octeon_device *octdev, u32 flag)
|
||||
{
|
||||
return !!(octdev->priv_flags & (0x1 << flag));
|
||||
}
|
||||
|
||||
static inline void lio_set_priv_flag(struct octeon_device *octdev,
|
||||
u32 flag, u32 val)
|
||||
{
|
||||
if (val)
|
||||
octdev->priv_flags |= (0x1 << flag);
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "octeon_network.h"
|
||||
#include "cn66xx_regs.h"
|
||||
#include "cn66xx_device.h"
|
||||
#include "cn23xx_pf_device.h"
|
||||
|
||||
#define CVM_MIN(d1, d2) (((d1) < (d2)) ? (d1) : (d2))
|
||||
#define CVM_MAX(d1, d2) (((d1) > (d2)) ? (d1) : (d2))
|
||||
|
@ -262,6 +263,11 @@ int octeon_init_droq(struct octeon_device *oct,
|
|||
c_pkts_per_intr = (u32)CFG_GET_OQ_PKTS_PER_INTR(conf6x);
|
||||
c_refill_threshold =
|
||||
(u32)CFG_GET_OQ_REFILL_THRESHOLD(conf6x);
|
||||
} else if (OCTEON_CN23XX_PF(oct)) {
|
||||
struct octeon_config *conf23 = CHIP_FIELD(oct, cn23xx_pf, conf);
|
||||
|
||||
c_pkts_per_intr = (u32)CFG_GET_OQ_PKTS_PER_INTR(conf23);
|
||||
c_refill_threshold = (u32)CFG_GET_OQ_REFILL_THRESHOLD(conf23);
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
|
@ -567,7 +573,7 @@ octeon_droq_dispatch_pkt(struct octeon_device *oct,
|
|||
(unsigned int)rh->r.opcode,
|
||||
(unsigned int)rh->r.subcode);
|
||||
droq->stats.dropped_nodispatch++;
|
||||
} /* else (dispatch_fn ... */
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
@ -881,8 +887,11 @@ octeon_process_droq_poll_cmd(struct octeon_device *oct, u32 q_no, int cmd,
|
|||
return 0;
|
||||
}
|
||||
break;
|
||||
case OCTEON_CN23XX_PF_VID: {
|
||||
lio_enable_irq(oct->droq[q_no], oct->instr_queue[q_no]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -181,22 +181,26 @@ cnnic_numa_alloc_aligned_dma(u32 size,
|
|||
#define cnnic_free_aligned_dma(pci_dev, ptr, size, orig_ptr, dma_addr) \
|
||||
free_pages(orig_ptr, get_order(size))
|
||||
|
||||
static inline void
|
||||
static inline int
|
||||
sleep_cond(wait_queue_head_t *wait_queue, int *condition)
|
||||
{
|
||||
int errno = 0;
|
||||
wait_queue_t we;
|
||||
|
||||
init_waitqueue_entry(&we, current);
|
||||
add_wait_queue(wait_queue, &we);
|
||||
while (!(READ_ONCE(*condition))) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
if (signal_pending(current))
|
||||
if (signal_pending(current)) {
|
||||
errno = -EINTR;
|
||||
goto out;
|
||||
}
|
||||
schedule();
|
||||
}
|
||||
out:
|
||||
set_current_state(TASK_RUNNING);
|
||||
remove_wait_queue(wait_queue, &we);
|
||||
return errno;
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
|
@ -122,11 +122,21 @@ struct lio {
|
|||
|
||||
/* work queue for txq status */
|
||||
struct cavium_wq txq_status_wq;
|
||||
|
||||
/* work queue for link status */
|
||||
struct cavium_wq link_status_wq;
|
||||
|
||||
};
|
||||
|
||||
#define LIO_SIZE (sizeof(struct lio))
|
||||
#define GET_LIO(netdev) ((struct lio *)netdev_priv(netdev))
|
||||
|
||||
#define CIU3_WDOG(c) (0x1010000020000ULL + (c << 3))
|
||||
#define CIU3_WDOG_MASK 12ULL
|
||||
#define LIO_MONITOR_WDOG_EXPIRE 1
|
||||
#define LIO_MONITOR_CORE_STUCK_MSGD 2
|
||||
#define LIO_MAX_CORES 12
|
||||
|
||||
/**
|
||||
* \brief Enable or disable feature
|
||||
* @param netdev pointer to network device
|
||||
|
|
|
@ -35,6 +35,7 @@ octeon_alloc_soft_command_resp(struct octeon_device *oct,
|
|||
u32 rdatasize)
|
||||
{
|
||||
struct octeon_soft_command *sc;
|
||||
struct octeon_instr_ih3 *ih3;
|
||||
struct octeon_instr_ih2 *ih2;
|
||||
struct octeon_instr_irh *irh;
|
||||
struct octeon_instr_rdp *rdp;
|
||||
|
@ -51,10 +52,19 @@ octeon_alloc_soft_command_resp(struct octeon_device *oct,
|
|||
/* Add in the response related fields. Opcode and Param are already
|
||||
* there.
|
||||
*/
|
||||
ih2 = (struct octeon_instr_ih2 *)&sc->cmd.cmd2.ih2;
|
||||
rdp = (struct octeon_instr_rdp *)&sc->cmd.cmd2.rdp;
|
||||
irh = (struct octeon_instr_irh *)&sc->cmd.cmd2.irh;
|
||||
ih2->fsz = 40; /* irh + ossp[0] + ossp[1] + rdp + rptr = 40 bytes */
|
||||
if (OCTEON_CN23XX_PF(oct)) {
|
||||
ih3 = (struct octeon_instr_ih3 *)&sc->cmd.cmd3.ih3;
|
||||
rdp = (struct octeon_instr_rdp *)&sc->cmd.cmd3.rdp;
|
||||
irh = (struct octeon_instr_irh *)&sc->cmd.cmd3.irh;
|
||||
/*pkiih3 + irh + ossp[0] + ossp[1] + rdp + rptr = 40 bytes */
|
||||
ih3->fsz = LIO_SOFTCMDRESP_IH3;
|
||||
} else {
|
||||
ih2 = (struct octeon_instr_ih2 *)&sc->cmd.cmd2.ih2;
|
||||
rdp = (struct octeon_instr_rdp *)&sc->cmd.cmd2.rdp;
|
||||
irh = (struct octeon_instr_irh *)&sc->cmd.cmd2.irh;
|
||||
/* irh + ossp[0] + ossp[1] + rdp + rptr = 40 bytes */
|
||||
ih2->fsz = LIO_SOFTCMDRESP_IH2;
|
||||
}
|
||||
|
||||
irh->rflag = 1; /* a response is required */
|
||||
|
||||
|
@ -63,7 +73,10 @@ octeon_alloc_soft_command_resp(struct octeon_device *oct,
|
|||
|
||||
*sc->status_word = COMPLETION_WORD_INIT;
|
||||
|
||||
sc->cmd.cmd2.rptr = sc->dmarptr;
|
||||
if (OCTEON_CN23XX_PF(oct))
|
||||
sc->cmd.cmd3.rptr = sc->dmarptr;
|
||||
else
|
||||
sc->cmd.cmd2.rptr = sc->dmarptr;
|
||||
|
||||
sc->wait_time = 1000;
|
||||
sc->timeout = jiffies + sc->wait_time;
|
||||
|
@ -179,8 +192,8 @@ octnet_send_nic_ctrl_pkt(struct octeon_device *oct,
|
|||
retval = octeon_send_soft_command(oct, sc);
|
||||
if (retval == IQ_SEND_FAILED) {
|
||||
octeon_free_soft_command(oct, sc);
|
||||
dev_err(&oct->pci_dev->dev, "%s soft command:%d send failed status: %x\n",
|
||||
__func__, nctrl->ncmd.s.cmd, retval);
|
||||
dev_err(&oct->pci_dev->dev, "%s pf_num:%d soft command:%d send failed status: %x\n",
|
||||
__func__, oct->pf_num, nctrl->ncmd.s.cmd, retval);
|
||||
spin_unlock_bh(&oct->cmd_resp_wqlock);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -138,7 +138,7 @@ octnet_prepare_pci_cmd_o2(struct octeon_device *oct,
|
|||
/* assume that rflag is cleared so therefore front data will only have
|
||||
* irh and ossp[0], ossp[1] for a total of 32 bytes
|
||||
*/
|
||||
ih2->fsz = 24;
|
||||
ih2->fsz = LIO_PCICMD_O2;
|
||||
|
||||
ih2->tagtype = ORDERED_TAG;
|
||||
ih2->grp = DEFAULT_POW_GRP;
|
||||
|
@ -196,7 +196,7 @@ octnet_prepare_pci_cmd_o3(struct octeon_device *oct,
|
|||
*/
|
||||
ih3->pkind = oct->instr_queue[setup->s.iq_no]->txpciq.s.pkind;
|
||||
/*PKI IH*/
|
||||
ih3->fsz = 24 + 8;
|
||||
ih3->fsz = LIO_PCICMD_O3;
|
||||
|
||||
if (!setup->s.gather) {
|
||||
ih3->dlengsz = setup->s.u.datasize;
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "octeon_main.h"
|
||||
#include "octeon_network.h"
|
||||
#include "cn66xx_device.h"
|
||||
#include "cn23xx_pf_device.h"
|
||||
|
||||
#define INCR_INSTRQUEUE_PKT_COUNT(octeon_dev_ptr, iq_no, field, count) \
|
||||
(octeon_dev_ptr->instr_queue[iq_no]->stats.field += count)
|
||||
|
@ -71,7 +72,8 @@ int octeon_init_instr_queue(struct octeon_device *oct,
|
|||
|
||||
if (OCTEON_CN6XXX(oct))
|
||||
conf = &(CFG_GET_IQ_CFG(CHIP_FIELD(oct, cn6xxx, conf)));
|
||||
|
||||
else if (OCTEON_CN23XX_PF(oct))
|
||||
conf = &(CFG_GET_IQ_CFG(CHIP_FIELD(oct, cn23xx_pf, conf)));
|
||||
if (!conf) {
|
||||
dev_err(&oct->pci_dev->dev, "Unsupported Chip %x\n",
|
||||
oct->chip_id);
|
||||
|
@ -88,6 +90,7 @@ int octeon_init_instr_queue(struct octeon_device *oct,
|
|||
q_size = (u32)conf->instr_type * num_descs;
|
||||
|
||||
iq = oct->instr_queue[iq_no];
|
||||
|
||||
iq->oct_dev = oct;
|
||||
|
||||
set_dev_node(&oct->pci_dev->dev, numa_node);
|
||||
|
@ -181,6 +184,9 @@ int octeon_delete_instr_queue(struct octeon_device *oct, u32 iq_no)
|
|||
if (OCTEON_CN6XXX(oct))
|
||||
desc_size =
|
||||
CFG_GET_IQ_INSTR_TYPE(CHIP_FIELD(oct, cn6xxx, conf));
|
||||
else if (OCTEON_CN23XX_PF(oct))
|
||||
desc_size =
|
||||
CFG_GET_IQ_INSTR_TYPE(CHIP_FIELD(oct, cn23xx_pf, conf));
|
||||
|
||||
vfree(iq->request_list);
|
||||
|
||||
|
@ -383,7 +389,12 @@ lio_process_iq_request_list(struct octeon_device *oct,
|
|||
case REQTYPE_SOFT_COMMAND:
|
||||
sc = buf;
|
||||
|
||||
irh = (struct octeon_instr_irh *)&sc->cmd.cmd2.irh;
|
||||
if (OCTEON_CN23XX_PF(oct))
|
||||
irh = (struct octeon_instr_irh *)
|
||||
&sc->cmd.cmd3.irh;
|
||||
else
|
||||
irh = (struct octeon_instr_irh *)
|
||||
&sc->cmd.cmd2.irh;
|
||||
if (irh->rflag) {
|
||||
/* We're expecting a response from Octeon.
|
||||
* It's up to lio_process_ordered_list() to
|
||||
|
@ -583,6 +594,8 @@ octeon_prepare_soft_command(struct octeon_device *oct,
|
|||
{
|
||||
struct octeon_config *oct_cfg;
|
||||
struct octeon_instr_ih2 *ih2;
|
||||
struct octeon_instr_ih3 *ih3;
|
||||
struct octeon_instr_pki_ih3 *pki_ih3;
|
||||
struct octeon_instr_irh *irh;
|
||||
struct octeon_instr_rdp *rdp;
|
||||
|
||||
|
@ -591,36 +604,88 @@ octeon_prepare_soft_command(struct octeon_device *oct,
|
|||
|
||||
oct_cfg = octeon_get_conf(oct);
|
||||
|
||||
ih2 = (struct octeon_instr_ih2 *)&sc->cmd.cmd2.ih2;
|
||||
ih2->tagtype = ATOMIC_TAG;
|
||||
ih2->tag = LIO_CONTROL;
|
||||
ih2->raw = 1;
|
||||
ih2->grp = CFG_GET_CTRL_Q_GRP(oct_cfg);
|
||||
if (OCTEON_CN23XX_PF(oct)) {
|
||||
ih3 = (struct octeon_instr_ih3 *)&sc->cmd.cmd3.ih3;
|
||||
|
||||
if (sc->datasize) {
|
||||
ih2->dlengsz = sc->datasize;
|
||||
ih2->rs = 1;
|
||||
}
|
||||
ih3->pkind = oct->instr_queue[sc->iq_no]->txpciq.s.pkind;
|
||||
|
||||
irh = (struct octeon_instr_irh *)&sc->cmd.cmd2.irh;
|
||||
irh->opcode = opcode;
|
||||
irh->subcode = subcode;
|
||||
pki_ih3 = (struct octeon_instr_pki_ih3 *)&sc->cmd.cmd3.pki_ih3;
|
||||
|
||||
/* opcode/subcode specific parameters (ossp) */
|
||||
irh->ossp = irh_ossp;
|
||||
sc->cmd.cmd2.ossp[0] = ossp0;
|
||||
sc->cmd.cmd2.ossp[1] = ossp1;
|
||||
pki_ih3->w = 1;
|
||||
pki_ih3->raw = 1;
|
||||
pki_ih3->utag = 1;
|
||||
pki_ih3->uqpg =
|
||||
oct->instr_queue[sc->iq_no]->txpciq.s.use_qpg;
|
||||
pki_ih3->utt = 1;
|
||||
pki_ih3->tag = LIO_CONTROL;
|
||||
pki_ih3->tagtype = ATOMIC_TAG;
|
||||
pki_ih3->qpg =
|
||||
oct->instr_queue[sc->iq_no]->txpciq.s.qpg;
|
||||
pki_ih3->pm = 0x7;
|
||||
pki_ih3->sl = 8;
|
||||
|
||||
if (sc->rdatasize) {
|
||||
rdp = (struct octeon_instr_rdp *)&sc->cmd.cmd2.rdp;
|
||||
rdp->pcie_port = oct->pcie_port;
|
||||
rdp->rlen = sc->rdatasize;
|
||||
if (sc->datasize)
|
||||
ih3->dlengsz = sc->datasize;
|
||||
|
||||
irh = (struct octeon_instr_irh *)&sc->cmd.cmd3.irh;
|
||||
irh->opcode = opcode;
|
||||
irh->subcode = subcode;
|
||||
|
||||
/* opcode/subcode specific parameters (ossp) */
|
||||
irh->ossp = irh_ossp;
|
||||
sc->cmd.cmd3.ossp[0] = ossp0;
|
||||
sc->cmd.cmd3.ossp[1] = ossp1;
|
||||
|
||||
if (sc->rdatasize) {
|
||||
rdp = (struct octeon_instr_rdp *)&sc->cmd.cmd3.rdp;
|
||||
rdp->pcie_port = oct->pcie_port;
|
||||
rdp->rlen = sc->rdatasize;
|
||||
|
||||
irh->rflag = 1;
|
||||
/*PKI IH3*/
|
||||
/* pki_ih3 irh+ossp[0]+ossp[1]+rdp+rptr = 48 bytes */
|
||||
ih3->fsz = LIO_SOFTCMDRESP_IH3;
|
||||
} else {
|
||||
irh->rflag = 0;
|
||||
/*PKI IH3*/
|
||||
/* pki_h3 + irh + ossp[0] + ossp[1] = 32 bytes */
|
||||
ih3->fsz = LIO_PCICMD_O3;
|
||||
}
|
||||
|
||||
irh->rflag = 1;
|
||||
ih2->fsz = 40; /* irh+ossp[0]+ossp[1]+rdp+rptr = 40 bytes */
|
||||
} else {
|
||||
irh->rflag = 0;
|
||||
ih2->fsz = 24; /* irh + ossp[0] + ossp[1] = 24 bytes */
|
||||
ih2 = (struct octeon_instr_ih2 *)&sc->cmd.cmd2.ih2;
|
||||
ih2->tagtype = ATOMIC_TAG;
|
||||
ih2->tag = LIO_CONTROL;
|
||||
ih2->raw = 1;
|
||||
ih2->grp = CFG_GET_CTRL_Q_GRP(oct_cfg);
|
||||
|
||||
if (sc->datasize) {
|
||||
ih2->dlengsz = sc->datasize;
|
||||
ih2->rs = 1;
|
||||
}
|
||||
|
||||
irh = (struct octeon_instr_irh *)&sc->cmd.cmd2.irh;
|
||||
irh->opcode = opcode;
|
||||
irh->subcode = subcode;
|
||||
|
||||
/* opcode/subcode specific parameters (ossp) */
|
||||
irh->ossp = irh_ossp;
|
||||
sc->cmd.cmd2.ossp[0] = ossp0;
|
||||
sc->cmd.cmd2.ossp[1] = ossp1;
|
||||
|
||||
if (sc->rdatasize) {
|
||||
rdp = (struct octeon_instr_rdp *)&sc->cmd.cmd2.rdp;
|
||||
rdp->pcie_port = oct->pcie_port;
|
||||
rdp->rlen = sc->rdatasize;
|
||||
|
||||
irh->rflag = 1;
|
||||
/* irh+ossp[0]+ossp[1]+rdp+rptr = 40 bytes */
|
||||
ih2->fsz = LIO_SOFTCMDRESP_IH2;
|
||||
} else {
|
||||
irh->rflag = 0;
|
||||
/* irh + ossp[0] + ossp[1] = 24 bytes */
|
||||
ih2->fsz = LIO_PCICMD_O2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -628,23 +693,39 @@ int octeon_send_soft_command(struct octeon_device *oct,
|
|||
struct octeon_soft_command *sc)
|
||||
{
|
||||
struct octeon_instr_ih2 *ih2;
|
||||
struct octeon_instr_ih3 *ih3;
|
||||
struct octeon_instr_irh *irh;
|
||||
u32 len;
|
||||
|
||||
ih2 = (struct octeon_instr_ih2 *)&sc->cmd.cmd2.ih2;
|
||||
if (ih2->dlengsz) {
|
||||
WARN_ON(!sc->dmadptr);
|
||||
sc->cmd.cmd2.dptr = sc->dmadptr;
|
||||
if (OCTEON_CN23XX_PF(oct)) {
|
||||
ih3 = (struct octeon_instr_ih3 *)&sc->cmd.cmd3.ih3;
|
||||
if (ih3->dlengsz) {
|
||||
WARN_ON(!sc->dmadptr);
|
||||
sc->cmd.cmd3.dptr = sc->dmadptr;
|
||||
}
|
||||
irh = (struct octeon_instr_irh *)&sc->cmd.cmd3.irh;
|
||||
if (irh->rflag) {
|
||||
WARN_ON(!sc->dmarptr);
|
||||
WARN_ON(!sc->status_word);
|
||||
*sc->status_word = COMPLETION_WORD_INIT;
|
||||
sc->cmd.cmd3.rptr = sc->dmarptr;
|
||||
}
|
||||
len = (u32)ih3->dlengsz;
|
||||
} else {
|
||||
ih2 = (struct octeon_instr_ih2 *)&sc->cmd.cmd2.ih2;
|
||||
if (ih2->dlengsz) {
|
||||
WARN_ON(!sc->dmadptr);
|
||||
sc->cmd.cmd2.dptr = sc->dmadptr;
|
||||
}
|
||||
irh = (struct octeon_instr_irh *)&sc->cmd.cmd2.irh;
|
||||
if (irh->rflag) {
|
||||
WARN_ON(!sc->dmarptr);
|
||||
WARN_ON(!sc->status_word);
|
||||
*sc->status_word = COMPLETION_WORD_INIT;
|
||||
sc->cmd.cmd2.rptr = sc->dmarptr;
|
||||
}
|
||||
len = (u32)ih2->dlengsz;
|
||||
}
|
||||
irh = (struct octeon_instr_irh *)&sc->cmd.cmd2.irh;
|
||||
if (irh->rflag) {
|
||||
WARN_ON(!sc->dmarptr);
|
||||
WARN_ON(!sc->status_word);
|
||||
*sc->status_word = COMPLETION_WORD_INIT;
|
||||
|
||||
sc->cmd.cmd2.rptr = sc->dmarptr;
|
||||
}
|
||||
len = (u32)ih2->dlengsz;
|
||||
|
||||
if (sc->wait_time)
|
||||
sc->timeout = jiffies + sc->wait_time;
|
||||
|
|
|
@ -91,8 +91,13 @@ int lio_process_ordered_list(struct octeon_device *octeon_dev,
|
|||
|
||||
sc = (struct octeon_soft_command *)ordered_sc_list->
|
||||
head.next;
|
||||
rdp = (struct octeon_instr_rdp *)&sc->cmd.cmd2.rdp;
|
||||
rptr = sc->cmd.cmd2.rptr;
|
||||
if (OCTEON_CN23XX_PF(octeon_dev)) {
|
||||
rdp = (struct octeon_instr_rdp *)&sc->cmd.cmd3.rdp;
|
||||
rptr = sc->cmd.cmd3.rptr;
|
||||
} else {
|
||||
rdp = (struct octeon_instr_rdp *)&sc->cmd.cmd2.rdp;
|
||||
rptr = sc->cmd.cmd2.rptr;
|
||||
}
|
||||
|
||||
status = OCTEON_REQUEST_PENDING;
|
||||
|
||||
|
|
Loading…
Reference in New Issue