diff options
Diffstat (limited to 'drivers/net/ethernet/cavium')
12 files changed, 341 insertions, 190 deletions
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_core.c b/drivers/net/ethernet/cavium/liquidio/lio_core.c index 32ae63b6f20e..666cf7e9cd09 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_core.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_core.c @@ -164,15 +164,6 @@ void liquidio_link_ctrl_cmd_completion(void *nctrl_ptr) } break; - case OCTNET_CMD_CHANGE_MTU: - /* If command is successful, change the MTU. */ - netif_info(lio, probe, lio->netdev, "MTU Changed from %d to %d\n", - netdev->mtu, nctrl->ncmd.s.param1); - netdev->mtu = nctrl->ncmd.s.param1; - 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"); @@ -571,7 +562,8 @@ liquidio_push_packet(u32 octeon_id __attribute__((unused)), napi_gro_receive(napi, skb); - droq->stats.rx_bytes_received += len; + droq->stats.rx_bytes_received += len - + rh->r_dh.len * BYTES_PER_DHLEN_UNIT; droq->stats.rx_pkts_received++; } else { recv_buffer_free(skb); @@ -635,9 +627,7 @@ static int liquidio_napi_poll(struct napi_struct *napi, int budget) iq_no = droq->q_no; /* Handle Droq descriptors */ - work_done = octeon_process_droq_poll_cmd(oct, droq->q_no, - POLL_EVENT_PROCESS_PKTS, - budget); + work_done = octeon_droq_process_poll_pkts(oct, droq, budget); /* Flush the instruction queue */ iq = oct->instr_queue[iq_no]; @@ -668,8 +658,7 @@ static int liquidio_napi_poll(struct napi_struct *napi, int budget) tx_done = 1; napi_complete_done(napi, work_done); - octeon_process_droq_poll_cmd(droq->oct_dev, droq->q_no, - POLL_EVENT_ENABLE_INTR, 0); + octeon_enable_irq(droq->oct_dev, droq->q_no); return 0; } @@ -1080,3 +1069,88 @@ int octeon_setup_interrupt(struct octeon_device *oct, u32 num_ioqs) } return 0; } + +static void liquidio_change_mtu_completion(struct octeon_device *oct, + u32 status, void *buf) +{ + struct octeon_soft_command *sc = (struct octeon_soft_command *)buf; + struct liquidio_if_cfg_context *ctx; + + ctx = (struct liquidio_if_cfg_context *)sc->ctxptr; + + if (status) { + dev_err(&oct->pci_dev->dev, "MTU change failed. Status: %llx\n", + CVM_CAST64(status)); + WRITE_ONCE(ctx->cond, LIO_CHANGE_MTU_FAIL); + } else { + WRITE_ONCE(ctx->cond, LIO_CHANGE_MTU_SUCCESS); + } + + /* 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 Net device change_mtu + * @param netdev network device + */ +int liquidio_change_mtu(struct net_device *netdev, int new_mtu) +{ + struct lio *lio = GET_LIO(netdev); + struct octeon_device *oct = lio->oct_dev; + struct liquidio_if_cfg_context *ctx; + struct octeon_soft_command *sc; + union octnet_cmd *ncmd; + int ctx_size; + int ret = 0; + + ctx_size = sizeof(struct liquidio_if_cfg_context); + sc = (struct octeon_soft_command *) + octeon_alloc_soft_command(oct, OCTNET_CMD_SIZE, 16, ctx_size); + + ncmd = (union octnet_cmd *)sc->virtdptr; + ctx = (struct liquidio_if_cfg_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_CHANGE_MTU; + ncmd->s.param1 = new_mtu; + + 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 = liquidio_change_mtu_completion; + sc->callback_arg = sc; + sc->wait_time = 100; + + ret = octeon_send_soft_command(oct, sc); + if (ret == IQ_SEND_FAILED) { + netif_info(lio, rx_err, lio->netdev, "Failed to change MTU\n"); + return -EINVAL; + } + /* 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 || + ctx->cond == LIO_CHANGE_MTU_FAIL) { + octeon_free_soft_command(oct, sc); + return -EINVAL; + } + + netdev->mtu = new_mtu; + lio->mtu = new_mtu; + + octeon_free_soft_command(oct, sc); + return 0; +} diff --git a/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c b/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c index a63ddf07f168..550ac29682a5 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c @@ -232,10 +232,16 @@ static int lio_get_link_ksettings(struct net_device *netdev, linfo = &lio->linfo; - if (linfo->link.s.if_mode == INTERFACE_MODE_XAUI || - linfo->link.s.if_mode == INTERFACE_MODE_RXAUI || - linfo->link.s.if_mode == INTERFACE_MODE_XLAUI || - linfo->link.s.if_mode == INTERFACE_MODE_XFI) { + switch (linfo->link.s.phy_type) { + case LIO_PHY_PORT_TP: + ecmd->base.port = PORT_TP; + supported = (SUPPORTED_10000baseT_Full | + SUPPORTED_TP | SUPPORTED_Pause); + advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_Pause); + ecmd->base.autoneg = AUTONEG_DISABLE; + break; + + case LIO_PHY_PORT_FIBRE: ecmd->base.port = PORT_FIBRE; if (linfo->link.s.speed == SPEED_10000) { @@ -245,12 +251,18 @@ static int lio_get_link_ksettings(struct net_device *netdev, supported |= SUPPORTED_FIBRE | SUPPORTED_Pause; advertising |= ADVERTISED_Pause; + ecmd->base.autoneg = AUTONEG_DISABLE; + break; + } + + if (linfo->link.s.if_mode == INTERFACE_MODE_XAUI || + linfo->link.s.if_mode == INTERFACE_MODE_RXAUI || + linfo->link.s.if_mode == INTERFACE_MODE_XLAUI || + linfo->link.s.if_mode == INTERFACE_MODE_XFI) { ethtool_convert_legacy_u32_to_link_mode( ecmd->link_modes.supported, supported); ethtool_convert_legacy_u32_to_link_mode( ecmd->link_modes.advertising, advertising); - ecmd->base.autoneg = AUTONEG_DISABLE; - } else { dev_err(&oct->pci_dev->dev, "Unknown link interface reported %d\n", linfo->link.s.if_mode); diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c index a5eecd895a82..21280cb66550 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c @@ -91,18 +91,9 @@ static int octeon_console_debug_enabled(u32 console) */ #define LIO_SYNC_OCTEON_TIME_INTERVAL_MS 60000 -struct liquidio_if_cfg_context { - int octeon_id; - - wait_queue_head_t wc; - - int cond; -}; - -struct liquidio_if_cfg_resp { - u64 rh; - struct liquidio_if_cfg_info cfg_info; - u64 status; +struct lio_trusted_vf_ctx { + struct completion complete; + int status; }; struct liquidio_rx_ctl_context { @@ -841,8 +832,12 @@ 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; + /* lio->linfo.link.s.mtu always contains max MTU of the lio interface. + * this API is invoked only when new max-MTU of the interface is + * less than current MTU. + */ rtnl_lock(); - call_netdevice_notifiers(NETDEV_CHANGEMTU, lio->netdev); + dev_set_mtu(lio->netdev, lio->linfo.link.s.mtu); rtnl_unlock(); } @@ -891,7 +886,11 @@ static inline void update_link_status(struct net_device *netdev, { struct lio *lio = GET_LIO(netdev); int changed = (lio->linfo.link.u64 != ls->u64); + int current_max_mtu = lio->linfo.link.s.mtu; + struct octeon_device *oct = lio->oct_dev; + dev_dbg(&oct->pci_dev->dev, "%s: lio->linfo.link.u64=%llx, ls->u64=%llx\n", + __func__, lio->linfo.link.u64, ls->u64); lio->linfo.link.u64 = ls->u64; if ((lio->intf_open) && (changed)) { @@ -899,12 +898,26 @@ static inline void update_link_status(struct net_device *netdev, lio->link_changes++; if (lio->linfo.link.s.link_up) { + dev_dbg(&oct->pci_dev->dev, "%s: link_up", __func__); netif_carrier_on(netdev); txqs_wake(netdev); } else { + dev_dbg(&oct->pci_dev->dev, "%s: link_off", __func__); netif_carrier_off(netdev); stop_txq(netdev); } + if (lio->linfo.link.s.mtu != current_max_mtu) { + netif_info(lio, probe, lio->netdev, "Max MTU changed from %d to %d\n", + current_max_mtu, lio->linfo.link.s.mtu); + netdev->max_mtu = lio->linfo.link.s.mtu; + } + if (lio->linfo.link.s.mtu < netdev->mtu) { + dev_warn(&oct->pci_dev->dev, + "Current MTU is higher than new max MTU; Reducing the current mtu from %d to %d\n", + netdev->mtu, lio->linfo.link.s.mtu); + queue_delayed_work(lio->link_status_wq.wq, + &lio->link_status_wq.wk.work, 0); + } } } @@ -2449,38 +2462,6 @@ static struct net_device_stats *liquidio_get_stats(struct net_device *netdev) } /** - * \brief Net device change_mtu - * @param netdev network device - */ -static int liquidio_change_mtu(struct net_device *netdev, int new_mtu) -{ - 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_CHANGE_MTU; - nctrl.ncmd.s.param1 = new_mtu; - 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 set MTU\n"); - return -1; - } - - lio->mtu = new_mtu; - - return 0; -} - -/** * \brief Handler for SIOCSHWTSTAMP ioctl * @param netdev network device * @param ifr interface request @@ -3289,10 +3270,120 @@ static int liquidio_get_vf_config(struct net_device *netdev, int vfidx, ether_addr_copy(&ivi->mac[0], macaddr); ivi->vlan = oct->sriov_info.vf_vlantci[vfidx] & VLAN_VID_MASK; ivi->qos = oct->sriov_info.vf_vlantci[vfidx] >> VLAN_PRIO_SHIFT; + if (oct->sriov_info.trusted_vf.active && + oct->sriov_info.trusted_vf.id == vfidx) + ivi->trusted = true; + else + ivi->trusted = false; ivi->linkstate = oct->sriov_info.vf_linkstate[vfidx]; return 0; } +static void trusted_vf_callback(struct octeon_device *oct_dev, + u32 status, void *ptr) +{ + struct octeon_soft_command *sc = (struct octeon_soft_command *)ptr; + struct lio_trusted_vf_ctx *ctx; + + ctx = (struct lio_trusted_vf_ctx *)sc->ctxptr; + ctx->status = status; + + complete(&ctx->complete); +} + +static int liquidio_send_vf_trust_cmd(struct lio *lio, int vfidx, bool trusted) +{ + struct octeon_device *oct = lio->oct_dev; + struct lio_trusted_vf_ctx *ctx; + struct octeon_soft_command *sc; + int ctx_size, retval; + + ctx_size = sizeof(struct lio_trusted_vf_ctx); + sc = octeon_alloc_soft_command(oct, 0, 0, ctx_size); + + ctx = (struct lio_trusted_vf_ctx *)sc->ctxptr; + init_completion(&ctx->complete); + + sc->iq_no = lio->linfo.txpciq[0].s.q_no; + + /* vfidx is 0 based, but vf_num (param1) is 1 based */ + octeon_prepare_soft_command(oct, sc, OPCODE_NIC, + OPCODE_NIC_SET_TRUSTED_VF, 0, vfidx + 1, + trusted); + + sc->callback = trusted_vf_callback; + sc->callback_arg = sc; + sc->wait_time = 1000; + + retval = octeon_send_soft_command(oct, sc); + if (retval == IQ_SEND_FAILED) { + retval = -1; + } else { + /* Wait for response or timeout */ + if (wait_for_completion_timeout(&ctx->complete, + msecs_to_jiffies(2000))) + retval = ctx->status; + else + retval = -1; + } + + octeon_free_soft_command(oct, sc); + + return retval; +} + +static int liquidio_set_vf_trust(struct net_device *netdev, int vfidx, + bool setting) +{ + struct lio *lio = GET_LIO(netdev); + struct octeon_device *oct = lio->oct_dev; + + if (strcmp(oct->fw_info.liquidio_firmware_version, "1.7.1") < 0) { + /* trusted vf is not supported by firmware older than 1.7.1 */ + return -EOPNOTSUPP; + } + + if (vfidx < 0 || vfidx >= oct->sriov_info.num_vfs_alloced) { + netif_info(lio, drv, lio->netdev, "Invalid vfidx %d\n", vfidx); + return -EINVAL; + } + + if (setting) { + /* Set */ + + if (oct->sriov_info.trusted_vf.active && + oct->sriov_info.trusted_vf.id == vfidx) + return 0; + + if (oct->sriov_info.trusted_vf.active) { + netif_info(lio, drv, lio->netdev, "More than one trusted VF is not allowed\n"); + return -EPERM; + } + } else { + /* Clear */ + + if (!oct->sriov_info.trusted_vf.active) + return 0; + } + + if (!liquidio_send_vf_trust_cmd(lio, vfidx, setting)) { + if (setting) { + oct->sriov_info.trusted_vf.id = vfidx; + oct->sriov_info.trusted_vf.active = true; + } else { + oct->sriov_info.trusted_vf.active = false; + } + + netif_info(lio, drv, lio->netdev, "VF %u is %strusted\n", vfidx, + setting ? "" : "not "); + } else { + netif_info(lio, drv, lio->netdev, "Failed to set VF trusted\n"); + return -1; + } + + return 0; +} + static int liquidio_set_vf_link_state(struct net_device *netdev, int vfidx, int linkstate) { @@ -3423,6 +3514,7 @@ static const struct net_device_ops lionetdevops = { .ndo_set_vf_mac = liquidio_set_vf_mac, .ndo_set_vf_vlan = liquidio_set_vf_vlan, .ndo_get_vf_config = liquidio_get_vf_config, + .ndo_set_vf_trust = liquidio_set_vf_trust, .ndo_set_vf_link_state = liquidio_set_vf_link_state, }; diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c index fd70a4844e2d..3342d64b7081 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c @@ -40,20 +40,6 @@ MODULE_PARM_DESC(debug, "NETIF_MSG debug bits"); #define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK) -struct liquidio_if_cfg_context { - int octeon_id; - - wait_queue_head_t wc; - - int cond; -}; - -struct liquidio_if_cfg_resp { - u64 rh; - struct liquidio_if_cfg_info cfg_info; - u64 status; -}; - struct liquidio_rx_ctl_context { int octeon_id; @@ -564,8 +550,12 @@ 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; + /* lio->linfo.link.s.mtu always contains max MTU of the lio interface. + * this API is invoked only when new max-MTU of the interface is + * less than current MTU. + */ rtnl_lock(); - call_netdevice_notifiers(NETDEV_CHANGEMTU, lio->netdev); + dev_set_mtu(lio->netdev, lio->linfo.link.s.mtu); rtnl_unlock(); } @@ -613,6 +603,7 @@ static void update_link_status(struct net_device *netdev, union oct_link_status *ls) { struct lio *lio = GET_LIO(netdev); + int current_max_mtu = lio->linfo.link.s.mtu; struct octeon_device *oct = lio->oct_dev; if ((lio->intf_open) && (lio->linfo.link.u64 != ls->u64)) { @@ -629,18 +620,17 @@ static void update_link_status(struct net_device *netdev, txqs_stop(netdev); } - if (lio->linfo.link.s.mtu != netdev->max_mtu) { - dev_info(&oct->pci_dev->dev, "Max MTU Changed from %d to %d\n", - netdev->max_mtu, lio->linfo.link.s.mtu); + if (lio->linfo.link.s.mtu != current_max_mtu) { + dev_info(&oct->pci_dev->dev, + "Max MTU Changed from %d to %d\n", + current_max_mtu, lio->linfo.link.s.mtu); netdev->max_mtu = lio->linfo.link.s.mtu; } if (lio->linfo.link.s.mtu < netdev->mtu) { dev_warn(&oct->pci_dev->dev, - "PF has changed the MTU for gmx port. Reducing the mtu from %d to %d\n", + "Current MTU is higher than new max MTU; Reducing the current mtu from %d to %d\n", netdev->mtu, lio->linfo.link.s.mtu); - lio->mtu = lio->linfo.link.s.mtu; - netdev->mtu = lio->linfo.link.s.mtu; queue_delayed_work(lio->link_status_wq.wq, &lio->link_status_wq.wk.work, 0); } @@ -1538,41 +1528,6 @@ static struct net_device_stats *liquidio_get_stats(struct net_device *netdev) } /** - * \brief Net device change_mtu - * @param netdev network device - */ -static int liquidio_change_mtu(struct net_device *netdev, int new_mtu) -{ - struct octnic_ctrl_pkt nctrl; - struct octeon_device *oct; - struct lio *lio; - int ret = 0; - - lio = GET_LIO(netdev); - oct = lio->oct_dev; - - memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt)); - - nctrl.ncmd.u64 = 0; - nctrl.ncmd.s.cmd = OCTNET_CMD_CHANGE_MTU; - nctrl.ncmd.s.param1 = new_mtu; - nctrl.iq_no = lio->linfo.txpciq[0].s.q_no; - nctrl.wait_time = LIO_CMD_WAIT_TM; - 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 set MTU\n"); - return -EIO; - } - - lio->mtu = new_mtu; - - return 0; -} - -/** * \brief Handler for SIOCSHWTSTAMP ioctl * @param netdev network device * @param ifr interface request diff --git a/drivers/net/ethernet/cavium/liquidio/liquidio_common.h b/drivers/net/ethernet/cavium/liquidio/liquidio_common.h index 522dcc4dcff7..82a783db5baf 100644 --- a/drivers/net/ethernet/cavium/liquidio/liquidio_common.h +++ b/drivers/net/ethernet/cavium/liquidio/liquidio_common.h @@ -84,6 +84,7 @@ enum octeon_tag_type { #define OPCODE_NIC_IF_CFG 0x09 #define OPCODE_NIC_VF_DRV_NOTICE 0x0A #define OPCODE_NIC_INTRMOD_PARAMS 0x0B +#define OPCODE_NIC_SET_TRUSTED_VF 0x13 #define OPCODE_NIC_SYNC_OCTEON_TIME 0x14 #define VF_DRV_LOADED 1 #define VF_DRV_REMOVED -1 @@ -192,7 +193,8 @@ static inline void add_sg_size(struct octeon_sg_entry *sg_entry, #define OCTNET_MAX_FRM_SIZE (16000 + OCTNET_FRM_HEADER_SIZE) -#define OCTNET_DEFAULT_FRM_SIZE (1500 + OCTNET_FRM_HEADER_SIZE) +#define OCTNET_DEFAULT_MTU (1500) +#define OCTNET_DEFAULT_FRM_SIZE (OCTNET_DEFAULT_MTU + OCTNET_FRM_HEADER_SIZE) /** NIC Commands are sent using this Octeon Input Queue */ #define OCTNET_CMD_Q 0 @@ -675,9 +677,11 @@ union oct_link_status { u64 if_mode:5; u64 pause:1; u64 flashing:1; - u64 reserved:15; + u64 phy_type:5; + u64 reserved:10; #else - u64 reserved:15; + u64 reserved:10; + u64 phy_type:5; u64 flashing:1; u64 pause:1; u64 if_mode:5; @@ -690,6 +694,12 @@ union oct_link_status { } s; }; +enum lio_phy_type { + LIO_PHY_PORT_TP = 0x0, + LIO_PHY_PORT_FIBRE = 0x1, + LIO_PHY_PORT_UNKNOWN, +}; + /** The txpciq info passed to host from the firmware */ union oct_txpciq { @@ -909,6 +919,12 @@ union oct_nic_if_cfg { } s; }; +struct lio_trusted_vf { + uint64_t active: 1; + uint64_t id : 8; + uint64_t reserved: 55; +}; + struct lio_time { s64 sec; /* seconds */ s64 nsec; /* nanoseconds */ diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_device.h b/drivers/net/ethernet/cavium/liquidio/octeon_device.h index 63b0c758a0a6..91937cc5c1d7 100644 --- a/drivers/net/ethernet/cavium/liquidio/octeon_device.h +++ b/drivers/net/ethernet/cavium/liquidio/octeon_device.h @@ -370,6 +370,8 @@ struct octeon_sriov_info { u32 sriov_enabled; + struct lio_trusted_vf trusted_vf; + /*lookup table that maps DPI ring number to VF pci_dev struct pointer*/ struct pci_dev *dpiring_to_vfpcidev_lut[MAX_POSSIBLE_VFS]; diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_droq.c b/drivers/net/ethernet/cavium/liquidio/octeon_droq.c index 3461d65ff4eb..f044718cea52 100644 --- a/drivers/net/ethernet/cavium/liquidio/octeon_droq.c +++ b/drivers/net/ethernet/cavium/liquidio/octeon_droq.c @@ -788,7 +788,7 @@ octeon_droq_process_packets(struct octeon_device *oct, * called before calling this routine. */ -static int +int octeon_droq_process_poll_pkts(struct octeon_device *oct, struct octeon_droq *droq, u32 budget) { @@ -835,71 +835,46 @@ octeon_droq_process_poll_pkts(struct octeon_device *oct, return total_pkts_processed; } +/* Enable Pkt Interrupt */ int -octeon_process_droq_poll_cmd(struct octeon_device *oct, u32 q_no, int cmd, - u32 arg) +octeon_enable_irq(struct octeon_device *oct, u32 q_no) { - struct octeon_droq *droq; - - droq = oct->droq[q_no]; + switch (oct->chip_id) { + case OCTEON_CN66XX: + case OCTEON_CN68XX: { + struct octeon_cn6xxx *cn6xxx = + (struct octeon_cn6xxx *)oct->chip; + unsigned long flags; + u32 value; - if (cmd == POLL_EVENT_PROCESS_PKTS) - return octeon_droq_process_poll_pkts(oct, droq, arg); + spin_lock_irqsave + (&cn6xxx->lock_for_droq_int_enb_reg, flags); + value = octeon_read_csr(oct, CN6XXX_SLI_PKT_TIME_INT_ENB); + value |= (1 << q_no); + octeon_write_csr(oct, CN6XXX_SLI_PKT_TIME_INT_ENB, value); + value = octeon_read_csr(oct, CN6XXX_SLI_PKT_CNT_INT_ENB); + value |= (1 << q_no); + octeon_write_csr(oct, CN6XXX_SLI_PKT_CNT_INT_ENB, value); - if (cmd == POLL_EVENT_PENDING_PKTS) { - u32 pkt_cnt = atomic_read(&droq->pkts_pending); + /* don't bother flushing the enables */ - return octeon_droq_process_packets(oct, droq, pkt_cnt); + spin_unlock_irqrestore + (&cn6xxx->lock_for_droq_int_enb_reg, flags); } - - if (cmd == POLL_EVENT_ENABLE_INTR) { - u32 value; - unsigned long flags; - - /* Enable Pkt Interrupt */ - switch (oct->chip_id) { - case OCTEON_CN66XX: - case OCTEON_CN68XX: { - struct octeon_cn6xxx *cn6xxx = - (struct octeon_cn6xxx *)oct->chip; - spin_lock_irqsave - (&cn6xxx->lock_for_droq_int_enb_reg, flags); - value = - octeon_read_csr(oct, - CN6XXX_SLI_PKT_TIME_INT_ENB); - value |= (1 << q_no); - octeon_write_csr(oct, - CN6XXX_SLI_PKT_TIME_INT_ENB, - value); - value = - octeon_read_csr(oct, - CN6XXX_SLI_PKT_CNT_INT_ENB); - value |= (1 << q_no); - octeon_write_csr(oct, - CN6XXX_SLI_PKT_CNT_INT_ENB, - value); - - /* don't bother flushing the enables */ - - spin_unlock_irqrestore - (&cn6xxx->lock_for_droq_int_enb_reg, flags); - return 0; - } break; - case OCTEON_CN23XX_PF_VID: { - lio_enable_irq(oct->droq[q_no], oct->instr_queue[q_no]); - } + case OCTEON_CN23XX_PF_VID: + lio_enable_irq(oct->droq[q_no], oct->instr_queue[q_no]); break; - case OCTEON_CN23XX_VF_VID: - lio_enable_irq(oct->droq[q_no], oct->instr_queue[q_no]); + case OCTEON_CN23XX_VF_VID: + lio_enable_irq(oct->droq[q_no], oct->instr_queue[q_no]); break; - } - return 0; + default: + dev_err(&oct->pci_dev->dev, "%s Unknown Chip\n", __func__); + return 1; } - dev_err(&oct->pci_dev->dev, "%s Unknown command: %d\n", __func__, cmd); - return -EINVAL; + return 0; } int octeon_register_droq_ops(struct octeon_device *oct, u32 q_no, diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_droq.h b/drivers/net/ethernet/cavium/liquidio/octeon_droq.h index 815a9f56fd59..f28f262d4ab6 100644 --- a/drivers/net/ethernet/cavium/liquidio/octeon_droq.h +++ b/drivers/net/ethernet/cavium/liquidio/octeon_droq.h @@ -123,11 +123,6 @@ struct oct_droq_stats { }; -#define POLL_EVENT_INTR_ARRIVED 1 -#define POLL_EVENT_PROCESS_PKTS 2 -#define POLL_EVENT_PENDING_PKTS 3 -#define POLL_EVENT_ENABLE_INTR 4 - /* The maximum number of buffers that can be dispatched from the * output/dma queue. Set to 64 assuming 1K buffers in DROQ and the fact that * max packet size from DROQ is 64K. @@ -414,8 +409,10 @@ int octeon_droq_process_packets(struct octeon_device *oct, struct octeon_droq *droq, u32 budget); -int octeon_process_droq_poll_cmd(struct octeon_device *oct, u32 q_no, - int cmd, u32 arg); +int octeon_droq_process_poll_pkts(struct octeon_device *oct, + struct octeon_droq *droq, u32 budget); + +int octeon_enable_irq(struct octeon_device *oct, u32 q_no); void octeon_droq_check_oom(struct octeon_droq *droq); diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.c b/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.c index 57af7df74ced..28e74ee23ff8 100644 --- a/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.c +++ b/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.c @@ -87,7 +87,7 @@ int octeon_mbox_read(struct octeon_mbox *mbox) } if (mbox->state & OCTEON_MBOX_STATE_REQUEST_RECEIVING) { - if (mbox->mbox_req.recv_len < msg.s.len) { + if (mbox->mbox_req.recv_len < mbox->mbox_req.msg.s.len) { ret = 0; } else { mbox->state &= ~OCTEON_MBOX_STATE_REQUEST_RECEIVING; @@ -96,7 +96,8 @@ int octeon_mbox_read(struct octeon_mbox *mbox) } } else { if (mbox->state & OCTEON_MBOX_STATE_RESPONSE_RECEIVING) { - if (mbox->mbox_resp.recv_len < msg.s.len) { + if (mbox->mbox_resp.recv_len < + mbox->mbox_resp.msg.s.len) { ret = 0; } else { mbox->state &= diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_network.h b/drivers/net/ethernet/cavium/liquidio/octeon_network.h index f2d1a076a038..76803a569794 100644 --- a/drivers/net/ethernet/cavium/liquidio/octeon_network.h +++ b/drivers/net/ethernet/cavium/liquidio/octeon_network.h @@ -35,6 +35,18 @@ #define LIO_IFSTATE_RX_TIMESTAMP_ENABLED 0x08 #define LIO_IFSTATE_RESETTING 0x10 +struct liquidio_if_cfg_context { + u32 octeon_id; + wait_queue_head_t wc; + int cond; +}; + +struct liquidio_if_cfg_resp { + u64 rh; + struct liquidio_if_cfg_info cfg_info; + u64 status; +}; + struct oct_nic_stats_resp { u64 rh; struct oct_link_stats stats; @@ -184,6 +196,14 @@ int octeon_setup_interrupt(struct octeon_device *oct, u32 num_ioqs); */ void liquidio_set_ethtool_ops(struct net_device *netdev); +/** + * \brief Net device change_mtu + * @param netdev network device + */ +int liquidio_change_mtu(struct net_device *netdev, int new_mtu); +#define LIO_CHANGE_MTU_SUCCESS 1 +#define LIO_CHANGE_MTU_FAIL 2 + #define SKB_ADJ_MASK 0x3F #define SKB_ADJ (SKB_ADJ_MASK + 1) diff --git a/drivers/net/ethernet/cavium/liquidio/request_manager.c b/drivers/net/ethernet/cavium/liquidio/request_manager.c index e07d2093b971..2766af05b89e 100644 --- a/drivers/net/ethernet/cavium/liquidio/request_manager.c +++ b/drivers/net/ethernet/cavium/liquidio/request_manager.c @@ -366,6 +366,7 @@ int lio_process_iq_request_list(struct octeon_device *oct, struct octeon_instr_queue *iq, u32 napi_budget) { + struct cavium_wq *cwq = &oct->dma_comp_wq; int reqtype; void *buf; u32 old = iq->flush_index; @@ -450,6 +451,10 @@ lio_process_iq_request_list(struct octeon_device *oct, bytes_compl); iq->flush_index = old; + if (atomic_read(&oct->response_list + [OCTEON_ORDERED_SC_LIST].pending_req_count)) + queue_delayed_work(cwq->wq, &cwq->wk.work, msecs_to_jiffies(1)); + return inst_count; } diff --git a/drivers/net/ethernet/cavium/liquidio/response_manager.c b/drivers/net/ethernet/cavium/liquidio/response_manager.c index 3d691c69f74d..fe5b53700576 100644 --- a/drivers/net/ethernet/cavium/liquidio/response_manager.c +++ b/drivers/net/ethernet/cavium/liquidio/response_manager.c @@ -49,7 +49,6 @@ int octeon_setup_response_list(struct octeon_device *oct) INIT_DELAYED_WORK(&cwq->wk.work, oct_poll_req_completion); cwq->wk.ctxptr = oct; oct->cmd_resp_state = OCT_DRV_ONLINE; - queue_delayed_work(cwq->wq, &cwq->wk.work, msecs_to_jiffies(50)); return ret; } @@ -164,5 +163,8 @@ static void oct_poll_req_completion(struct work_struct *work) struct cavium_wq *cwq = &oct->dma_comp_wq; lio_process_ordered_list(oct, 0); - queue_delayed_work(cwq->wq, &cwq->wk.work, msecs_to_jiffies(50)); + + if (atomic_read(&oct->response_list + [OCTEON_ORDERED_SC_LIST].pending_req_count)) + queue_delayed_work(cwq->wq, &cwq->wk.work, msecs_to_jiffies(1)); } |