Commit e8a3925f authored by David S. Miller's avatar David S. Miller

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 0cc1f315 30136395
...@@ -887,6 +887,67 @@ static irqreturn_t cn23xx_interrupt_handler(void *dev) ...@@ -887,6 +887,67 @@ static irqreturn_t cn23xx_interrupt_handler(void *dev)
return IRQ_HANDLED; 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) static void cn23xx_enable_pf_interrupt(struct octeon_device *oct, u8 intr_flag)
{ {
struct octeon_cn23xx_pf *cn23xx = (struct octeon_cn23xx_pf *)oct->chip; 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) ...@@ -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.soft_reset = cn23xx_pf_soft_reset;
oct->fn_list.setup_device_regs = cn23xx_setup_pf_device_regs; 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.enable_interrupt = cn23xx_enable_pf_interrupt;
oct->fn_list.disable_interrupt = cn23xx_disable_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); ...@@ -51,6 +51,8 @@ int setup_cn23xx_octeon_pf_device(struct octeon_device *oct);
int validate_cn23xx_pf_config_info(struct octeon_device *oct, int validate_cn23xx_pf_config_info(struct octeon_device *oct,
struct octeon_config *conf23xx); 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); void cn23xx_dump_pf_initialized_regs(struct octeon_device *oct);
int cn23xx_fw_loaded(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) ...@@ -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", dev_info(&oct->pci_dev->dev, "%s MTU Changed from %d to %d\n",
netdev->name, netdev->mtu, netdev->name, netdev->mtu,
nctrl->ncmd.s.param1); nctrl->ncmd.s.param1);
rtnl_lock();
netdev->mtu = nctrl->ncmd.s.param1; netdev->mtu = nctrl->ncmd.s.param1;
call_netdevice_notifiers(NETDEV_CHANGEMTU, netdev); queue_delayed_work(lio->link_status_wq.wq,
rtnl_unlock(); &lio->link_status_wq.wk.work, 0);
break; break;
case OCTNET_CMD_GPIO_ACCESS: case OCTNET_CMD_GPIO_ACCESS:
netif_info(lio, probe, lio->netdev, "LED Flashing visual identification\n"); 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; break;
case OCTNET_CMD_LRO_ENABLE: case OCTNET_CMD_LRO_ENABLE:
......
...@@ -232,6 +232,9 @@ static inline void add_sg_size(struct octeon_sg_entry *sg_entry, ...@@ -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_ADD_VLAN_FILTER 0x17
#define OCTNET_CMD_DEL_VLAN_FILTER 0x18 #define OCTNET_CMD_DEL_VLAN_FILTER 0x18
#define OCTNET_CMD_VXLAN_PORT_CONFIG 0x19 #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_ADD 0x0
#define OCTNET_CMD_VXLAN_PORT_DEL 0x1 #define OCTNET_CMD_VXLAN_PORT_DEL 0x1
#define OCTNET_CMD_RXCSUM_ENABLE 0x0 #define OCTNET_CMD_RXCSUM_ENABLE 0x0
...@@ -310,6 +313,13 @@ union octnet_cmd { ...@@ -310,6 +313,13 @@ union octnet_cmd {
#define OCTNET_CMD_SIZE (sizeof(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 */ /* Instruction Header(DPI) - for OCTEON-III models */
struct octeon_instr_ih3 { struct octeon_instr_ih3 {
#ifdef __BIG_ENDIAN_BITFIELD #ifdef __BIG_ENDIAN_BITFIELD
...@@ -828,6 +838,8 @@ struct oct_link_stats { ...@@ -828,6 +838,8 @@ struct oct_link_stats {
#define VITESSE_PHY_GPIO_DRIVEOFF 0x4 #define VITESSE_PHY_GPIO_DRIVEOFF 0x4
#define VITESSE_PHY_GPIO_HIGH 0x2 #define VITESSE_PHY_GPIO_HIGH 0x2
#define VITESSE_PHY_GPIO_LOW 0x3 #define VITESSE_PHY_GPIO_LOW 0x3
#define LED_IDENTIFICATION_ON 0x1
#define LED_IDENTIFICATION_OFF 0x0
struct oct_mdio_cmd { struct oct_mdio_cmd {
u64 op; u64 op;
......
...@@ -793,7 +793,6 @@ int octeon_setup_instr_queues(struct octeon_device *oct) ...@@ -793,7 +793,6 @@ int octeon_setup_instr_queues(struct octeon_device *oct)
union oct_txpciq txpciq; union oct_txpciq txpciq;
int numa_node = cpu_to_node(iq_no % num_online_cpus()); int numa_node = cpu_to_node(iq_no % num_online_cpus());
/* this causes queue 0 to be default queue */
if (OCTEON_CN6XXX(oct)) if (OCTEON_CN6XXX(oct))
num_descs = num_descs =
CFG_GET_NUM_DEF_TX_DESCS(CHIP_FIELD(oct, cn6xxx, conf)); CFG_GET_NUM_DEF_TX_DESCS(CHIP_FIELD(oct, cn6xxx, conf));
...@@ -816,6 +815,7 @@ int octeon_setup_instr_queues(struct octeon_device *oct) ...@@ -816,6 +815,7 @@ int octeon_setup_instr_queues(struct octeon_device *oct)
oct->instr_queue[0]->ifidx = 0; oct->instr_queue[0]->ifidx = 0;
txpciq.u64 = 0; txpciq.u64 = 0;
txpciq.s.q_no = iq_no; txpciq.s.q_no = iq_no;
txpciq.s.pkind = oct->pfvf_hsword.pkind;
txpciq.s.use_qpg = 0; txpciq.s.use_qpg = 0;
txpciq.s.qpg = 0; txpciq.s.qpg = 0;
if (octeon_init_instr_queue(oct, txpciq, num_descs)) { if (octeon_init_instr_queue(oct, txpciq, num_descs)) {
...@@ -835,7 +835,6 @@ int octeon_setup_output_queues(struct octeon_device *oct) ...@@ -835,7 +835,6 @@ int octeon_setup_output_queues(struct octeon_device *oct)
u32 oq_no = 0; u32 oq_no = 0;
int numa_node = cpu_to_node(oq_no % num_online_cpus()); int numa_node = cpu_to_node(oq_no % num_online_cpus());
/* this causes queue 0 to be default queue */
if (OCTEON_CN6XXX(oct)) { if (OCTEON_CN6XXX(oct)) {
num_descs = num_descs =
CFG_GET_NUM_DEF_RX_DESCS(CHIP_FIELD(oct, cn6xxx, conf)); CFG_GET_NUM_DEF_RX_DESCS(CHIP_FIELD(oct, cn6xxx, conf));
...@@ -863,10 +862,10 @@ int octeon_setup_output_queues(struct octeon_device *oct) ...@@ -863,10 +862,10 @@ int octeon_setup_output_queues(struct octeon_device *oct)
void octeon_set_io_queues_off(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. */ if (OCTEON_CN6XXX(oct)) {
octeon_write_csr(oct, CN6XXX_SLI_PKT_INSTR_ENB, 0);
octeon_write_csr(oct, CN6XXX_SLI_PKT_INSTR_ENB, 0); octeon_write_csr(oct, CN6XXX_SLI_PKT_OUT_ENB, 0);
octeon_write_csr(oct, CN6XXX_SLI_PKT_OUT_ENB, 0); }
} }
void octeon_set_droq_pkt_op(struct octeon_device *oct, void octeon_set_droq_pkt_op(struct octeon_device *oct,
...@@ -876,14 +875,16 @@ 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; u32 reg_val = 0;
/* Disable the i/p and o/p queues for this Octeon. */ /* 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) if (enable)
reg_val = reg_val | (1 << q_no); reg_val = reg_val | (1 << q_no);
else else
reg_val = reg_val & (~(1 << q_no)); 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) 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) ...@@ -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_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->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); atomic_set(&oct->status, OCT_DEV_CORE_OK);
...@@ -1294,17 +1301,36 @@ int lio_get_device_id(void *dev) ...@@ -1294,17 +1301,36 @@ int lio_get_device_id(void *dev)
void lio_enable_irq(struct octeon_droq *droq, struct octeon_instr_queue *iq) 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 */ /* the whole thing needs to be atomic, ideally */
if (droq) { if (droq) {
spin_lock_bh(&droq->lock); spin_lock_bh(&droq->lock);
writel(droq->pkt_count, droq->pkts_sent_reg); writel(droq->pkt_count, droq->pkts_sent_reg);
droq->pkt_count = 0; droq->pkt_count = 0;
spin_unlock_bh(&droq->lock); spin_unlock_bh(&droq->lock);
oct = droq->oct_dev;
} }
if (iq) { if (iq) {
spin_lock_bh(&iq->lock); spin_lock_bh(&iq->lock);
writel(iq->pkt_in_done, iq->inst_cnt_reg); writel(iq->pkt_in_done, iq->inst_cnt_reg);
iq->pkt_in_done = 0; iq->pkt_in_done = 0;
spin_unlock_bh(&iq->lock); 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 { ...@@ -275,6 +275,7 @@ struct octdev_props {
/* Each interface in the Octeon device has a network /* Each interface in the Octeon device has a network
* device pointer (used for OS specific calls). * device pointer (used for OS specific calls).
*/ */
int rx_on;
int napi_enabled; int napi_enabled;
int gmxport; int gmxport;
struct net_device *netdev; struct net_device *netdev;
...@@ -483,6 +484,8 @@ struct octeon_device { ...@@ -483,6 +484,8 @@ struct octeon_device {
/* private flags to control driver-specific features through ethtool */ /* private flags to control driver-specific features through ethtool */
u32 priv_flags; u32 priv_flags;
void *watchdog_task;
}; };
#define OCT_DRV_ONLINE 1 #define OCT_DRV_ONLINE 1
...@@ -752,8 +755,15 @@ enum { ...@@ -752,8 +755,15 @@ enum {
OCT_PRIV_FLAG_TX_BYTES = 0, /* Tx interrupts by pending byte count */ 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, #define OCT_PRIV_FLAG_DEFAULT 0x0
u32 val)
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) if (val)
octdev->priv_flags |= (0x1 << flag); octdev->priv_flags |= (0x1 << flag);
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "octeon_network.h" #include "octeon_network.h"
#include "cn66xx_regs.h" #include "cn66xx_regs.h"
#include "cn66xx_device.h" #include "cn66xx_device.h"
#include "cn23xx_pf_device.h"
#define CVM_MIN(d1, d2) (((d1) < (d2)) ? (d1) : (d2)) #define CVM_MIN(d1, d2) (((d1) < (d2)) ? (d1) : (d2))
#define CVM_MAX(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, ...@@ -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_pkts_per_intr = (u32)CFG_GET_OQ_PKTS_PER_INTR(conf6x);
c_refill_threshold = c_refill_threshold =
(u32)CFG_GET_OQ_REFILL_THRESHOLD(conf6x); (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 { } else {
return 1; return 1;
} }
...@@ -567,7 +573,7 @@ octeon_droq_dispatch_pkt(struct octeon_device *oct, ...@@ -567,7 +573,7 @@ octeon_droq_dispatch_pkt(struct octeon_device *oct,
(unsigned int)rh->r.opcode, (unsigned int)rh->r.opcode,
(unsigned int)rh->r.subcode); (unsigned int)rh->r.subcode);
droq->stats.dropped_nodispatch++; droq->stats.dropped_nodispatch++;
} /* else (dispatch_fn ... */ }
return cnt; return cnt;
} }
...@@ -881,8 +887,11 @@ octeon_process_droq_poll_cmd(struct octeon_device *oct, u32 q_no, int cmd, ...@@ -881,8 +887,11 @@ octeon_process_droq_poll_cmd(struct octeon_device *oct, u32 q_no, int cmd,
return 0; return 0;
} }
break; break;
case OCTEON_CN23XX_PF_VID: {
lio_enable_irq(oct->droq[q_no], oct->instr_queue[q_no]);
}
break;
} }
return 0; return 0;
} }
......
...@@ -181,22 +181,26 @@ cnnic_numa_alloc_aligned_dma(u32 size, ...@@ -181,22 +181,26 @@ cnnic_numa_alloc_aligned_dma(u32 size,
#define cnnic_free_aligned_dma(pci_dev, ptr, size, orig_ptr, dma_addr) \ #define cnnic_free_aligned_dma(pci_dev, ptr, size, orig_ptr, dma_addr) \
free_pages(orig_ptr, get_order(size)) free_pages(orig_ptr, get_order(size))
static inline void static inline int
sleep_cond(wait_queue_head_t *wait_queue, int *condition) sleep_cond(wait_queue_head_t *wait_queue, int *condition)
{ {
int errno = 0;
wait_queue_t we; wait_queue_t we;
init_waitqueue_entry(&we, current); init_waitqueue_entry(&we, current);
add_wait_queue(wait_queue, &we); add_wait_queue(wait_queue, &we);
while (!(READ_ONCE(*condition))) { while (!(READ_ONCE(*condition))) {
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
if (signal_pending(current)) if (signal_pending(current)) {
errno = -EINTR;
goto out; goto out;
}
schedule(); schedule();
} }
out: out:
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
remove_wait_queue(wait_queue, &we); remove_wait_queue(wait_queue, &we);
return errno;
} }
static inline void static inline void
......
...@@ -122,11 +122,21 @@ struct lio { ...@@ -122,11 +122,21 @@ struct lio {
/* work queue for txq status */ /* work queue for txq status */
struct cavium_wq txq_status_wq; struct cavium_wq txq_status_wq;
/* work queue for link status */
struct cavium_wq link_status_wq;
}; };
#define LIO_SIZE (sizeof(struct lio)) #define LIO_SIZE (sizeof(struct lio))
#define GET_LIO(netdev) ((struct lio *)netdev_priv(netdev)) #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 * \brief Enable or disable feature
* @param netdev pointer to network device * @param netdev pointer to network device
......
...@@ -35,6 +35,7 @@ octeon_alloc_soft_command_resp(struct octeon_device *oct, ...@@ -35,6 +35,7 @@ octeon_alloc_soft_command_resp(struct octeon_device *oct,
u32 rdatasize) u32 rdatasize)
{ {
struct octeon_soft_command *sc; struct octeon_soft_command *sc;
struct octeon_instr_ih3 *ih3;
struct octeon_instr_ih2 *ih2; struct octeon_instr_ih2 *ih2;
struct octeon_instr_irh *irh; struct octeon_instr_irh *irh;
struct octeon_instr_rdp *rdp; struct octeon_instr_rdp *rdp;
...@@ -51,10 +52,19 @@ octeon_alloc_soft_command_resp(struct octeon_device *oct, ...@@ -51,10 +52,19 @@ octeon_alloc_soft_command_resp(struct octeon_device *oct,
/* Add in the response related fields. Opcode and Param are already /* Add in the response related fields. Opcode and Param are already
* there. * there.
*/ */
ih2 = (struct octeon_instr_ih2 *)&sc->cmd.cmd2.ih2; if (OCTEON_CN23XX_PF(oct)) {
rdp = (struct octeon_instr_rdp *)&sc->cmd.cmd2.rdp; ih3 = (struct octeon_instr_ih3 *)&sc->cmd.cmd3.ih3;
irh = (struct octeon_instr_irh *)&sc->cmd.cmd2.irh; rdp = (struct octeon_instr_rdp *)&sc->cmd.cmd3.rdp;
ih2->fsz = 40; /* irh + ossp[0] + ossp[1] + rdp + rptr = 40 bytes */ 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 */ irh->rflag = 1; /* a response is required */
...@@ -63,7 +73,10 @@ octeon_alloc_soft_command_resp(struct octeon_device *oct, ...@@ -63,7 +73,10 @@ octeon_alloc_soft_command_resp(struct octeon_device *oct,
*sc->status_word = COMPLETION_WORD_INIT; *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->wait_time = 1000;
sc->timeout = jiffies + sc->wait_time; sc->timeout = jiffies + sc->wait_time;
...@@ -179,8 +192,8 @@ octnet_send_nic_ctrl_pkt(struct octeon_device *oct, ...@@ -179,8 +192,8 @@ octnet_send_nic_ctrl_pkt(struct octeon_device *oct,
retval = octeon_send_soft_command(oct, sc); retval = octeon_send_soft_command(oct, sc);
if (retval == IQ_SEND_FAILED) { if (retval == IQ_SEND_FAILED) {
octeon_free_soft_command(oct, sc); octeon_free_soft_command(oct, sc);
dev_err(&oct->pci_dev->dev, "%s soft command:%d send failed status: %x\n", dev_err(&oct->pci_dev->dev, "%s pf_num:%d soft command:%d send failed status: %x\n",
__func__, nctrl->ncmd.s.cmd, retval); __func__, oct->pf_num, nctrl->ncmd.s.cmd, retval);
spin_unlock_bh(&oct->cmd_resp_wqlock); spin_unlock_bh(&oct->cmd_resp_wqlock);
return -1; return -1;
} }
......
...@@ -138,7 +138,7 @@ octnet_prepare_pci_cmd_o2(struct octeon_device *oct, ...@@ -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 /* assume that rflag is cleared so therefore front data will only have
* irh and ossp[0], ossp[1] for a total of 32 bytes * 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->tagtype = ORDERED_TAG;
ih2->grp = DEFAULT_POW_GRP; ih2->grp = DEFAULT_POW_GRP;
...@@ -196,7 +196,7 @@ octnet_prepare_pci_cmd_o3(struct octeon_device *oct, ...@@ -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; ih3->pkind = oct->instr_queue[setup->s.iq_no]->txpciq.s.pkind;
/*PKI IH*/ /*PKI IH*/
ih3->fsz = 24 + 8; ih3->fsz = LIO_PCICMD_O3;
if (!setup->s.gather) { if (!setup->s.gather) {
ih3->dlengsz = setup->s.u.datasize; ih3->dlengsz = setup->s.u.datasize;
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "octeon_main.h" #include "octeon_main.h"
#include "octeon_network.h" #include "octeon_network.h"
#include "cn66xx_device.h" #include "cn66xx_device.h"
#include "cn23xx_pf_device.h"
#define INCR_INSTRQUEUE_PKT_COUNT(octeon_dev_ptr, iq_no, field, count) \ #define INCR_INSTRQUEUE_PKT_COUNT(octeon_dev_ptr, iq_no, field, count) \
(octeon_dev_ptr->instr_queue[iq_no]->stats.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, ...@@ -71,7 +72,8 @@ int octeon_init_instr_queue(struct octeon_device *oct,
if (OCTEON_CN6XXX(oct)) if (OCTEON_CN6XXX(oct))
conf = &(CFG_GET_IQ_CFG(CHIP_FIELD(oct, cn6xxx, conf))); 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) { if (!conf) {
dev_err(&oct->pci_dev->dev, "Unsupported Chip %x\n", dev_err(&oct->pci_dev->dev, "Unsupported Chip %x\n",
oct->chip_id); oct->chip_id);
...@@ -88,6 +90,7 @@ int octeon_init_instr_queue(struct octeon_device *oct, ...@@ -88,6 +90,7 @@ int octeon_init_instr_queue(struct octeon_device *oct,
q_size = (u32)conf->instr_type * num_descs; q_size = (u32)conf->instr_type * num_descs;
iq = oct->instr_queue[iq_no]; iq = oct->instr_queue[iq_no];
iq->oct_dev = oct; iq->oct_dev = oct;
set_dev_node(&oct->pci_dev->dev, numa_node); 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) ...@@ -181,6 +184,9 @@ int octeon_delete_instr_queue(struct octeon_device *oct, u32 iq_no)
if (OCTEON_CN6XXX(oct)) if (OCTEON_CN6XXX(oct))
desc_size = desc_size =
CFG_GET_IQ_INSTR_TYPE(CHIP_FIELD(oct, cn6xxx, conf)); 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); vfree(iq->request_list);
...@@ -383,7 +389,12 @@ lio_process_iq_request_list(struct octeon_device *oct, ...@@ -383,7 +389,12 @@ lio_process_iq_request_list(struct octeon_device *oct,
case REQTYPE_SOFT_COMMAND: case REQTYPE_SOFT_COMMAND:
sc = buf; 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) { if (irh->rflag) {
/* We're expecting a response from Octeon. /* We're expecting a response from Octeon.
* It's up to lio_process_ordered_list() to * It's up to lio_process_ordered_list() to
...@@ -583,6 +594,8 @@ octeon_prepare_soft_command(struct octeon_device *oct, ...@@ -583,6 +594,8 @@ octeon_prepare_soft_command(struct octeon_device *oct,
{ {
struct octeon_config *oct_cfg; struct octeon_config *oct_cfg;
struct octeon_instr_ih2 *ih2; 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_irh *irh;
struct octeon_instr_rdp *rdp; struct octeon_instr_rdp *rdp;
...@@ -591,36 +604,88 @@ octeon_prepare_soft_command(struct octeon_device *oct, ...@@ -591,36 +604,88 @@ octeon_prepare_soft_command(struct octeon_device *oct,
oct_cfg = octeon_get_conf(oct); oct_cfg = octeon_get_conf(oct);
ih2 = (struct octeon_instr_ih2 *)&sc->cmd.cmd2.ih2; if (OCTEON_CN23XX_PF(oct)) {
ih2->tagtype = ATOMIC_TAG; ih3 = (struct octeon_instr_ih3 *)&sc->cmd.cmd3.ih3;
ih2->tag = LIO_CONTROL;
ih2->raw = 1; ih3->pkind = oct->instr_queue[sc->iq_no]->txpciq.s.pkind;
ih2->grp = CFG_GET_CTRL_Q_GRP(oct_cfg);
pki_ih3 = (struct octeon_instr_pki_ih3 *)&sc->cmd.cmd3.pki_ih3;
if (sc->datasize) {
ih2->dlengsz = sc->datasize; pki_ih3->w = 1;
ih2->rs = 1; pki_ih3->raw = 1;
} pki_ih3->utag = 1;
pki_ih3->uqpg =
irh = (struct octeon_instr_irh *)&sc->cmd.cmd2.irh; oct->instr_queue[sc->iq_no]->txpciq.s.use_qpg;
irh->opcode = opcode; pki_ih3->utt = 1;
irh->subcode = subcode; pki_ih3->tag = LIO_CONTROL;
pki_ih3->tagtype = ATOMIC_TAG;
/* opcode/subcode specific parameters (ossp) */ pki_ih3->qpg =
irh->ossp = irh_ossp; oct->instr_queue[sc->iq_no]->txpciq.s.qpg;
sc->cmd.cmd2.ossp[0] = ossp0; pki_ih3->pm = 0x7;
sc->cmd.cmd2.ossp[1] = ossp1; pki_ih3->sl = 8;
if (sc->rdatasize) { if (sc->datasize)
rdp = (struct octeon_instr_rdp *)&sc->cmd.cmd2.rdp; ih3->dlengsz = sc->datasize;
rdp->pcie_port = oct->pcie_port;
rdp->rlen = sc->rdatasize; 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 { } else {
irh->rflag = 0; ih2 = (struct octeon_instr_ih2 *)&sc->cmd.cmd2.ih2;
ih2->fsz = 24; /* irh + ossp[0] + ossp[1] = 24 bytes */ 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, ...@@ -628,23 +693,39 @@ int octeon_send_soft_command(struct octeon_device *oct,
struct octeon_soft_command *sc) struct octeon_soft_command *sc)
{ {
struct octeon_instr_ih2 *ih2; struct octeon_instr_ih2 *ih2;
struct octeon_instr_ih3 *ih3;
struct octeon_instr_irh *irh; struct octeon_instr_irh *irh;
u32 len; u32 len;
ih2 = (struct octeon_instr_ih2 *)&sc->cmd.cmd2.ih2; if (OCTEON_CN23XX_PF(oct)) {
if (ih2->dlengsz) { ih3 = (struct octeon_instr_ih3 *)&sc->cmd.cmd3.ih3;
WARN_ON(!sc->dmadptr); if (ih3->dlengsz) {
sc->cmd.cmd2.dptr = sc->dmadptr; WARN_ON(!sc->dmadptr);
} sc->cmd.cmd3.dptr = sc->dmadptr;
irh = (struct octeon_instr_irh *)&sc->cmd.cmd2.irh; }
if (irh->rflag) { irh = (struct octeon_instr_irh *)&sc->cmd.cmd3.irh;
WARN_ON(!sc->dmarptr); if (irh->rflag) {
WARN_ON(!sc->status_word); WARN_ON(!sc->dmarptr);
*sc->status_word = COMPLETION_WORD_INIT; WARN_ON(!sc->status_word);
*sc->status_word = COMPLETION_WORD_INIT;
sc->cmd.cmd2.rptr = sc->dmarptr; 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;
} }
len = (u32)ih2->dlengsz;
if (sc->wait_time) if (sc->wait_time)
sc->timeout = jiffies + sc->wait_time; sc->timeout = jiffies + sc->wait_time;
......
...@@ -91,8 +91,13 @@ int lio_process_ordered_list(struct octeon_device *octeon_dev, ...@@ -91,8 +91,13 @@ int lio_process_ordered_list(struct octeon_device *octeon_dev,
sc = (struct octeon_soft_command *)ordered_sc_list-> sc = (struct octeon_soft_command *)ordered_sc_list->
head.next; head.next;
rdp = (struct octeon_instr_rdp *)&sc->cmd.cmd2.rdp; if (OCTEON_CN23XX_PF(octeon_dev)) {
rptr = sc->cmd.cmd2.rptr; 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; status = OCTEON_REQUEST_PENDING;
......
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