From 071106ecf68c401173c58808b1cf5f68cc50d390 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Fri, 05 Jan 2024 08:39:27 +0000 Subject: [PATCH] change wifi driver to cypress --- kernel/drivers/net/ethernet/cavium/liquidio/lio_main.c | 1000 +++++++++++++++++++++++++++++++--------------------------- 1 files changed, 529 insertions(+), 471 deletions(-) diff --git a/kernel/drivers/net/ethernet/cavium/liquidio/lio_main.c b/kernel/drivers/net/ethernet/cavium/liquidio/lio_main.c index 304e4b9..eefb25b 100644 --- a/kernel/drivers/net/ethernet/cavium/liquidio/lio_main.c +++ b/kernel/drivers/net/ethernet/cavium/liquidio/lio_main.c @@ -21,7 +21,6 @@ #include <linux/firmware.h> #include <net/vxlan.h> #include <linux/kthread.h> -#include <net/switchdev.h> #include "liquidio_common.h" #include "octeon_droq.h" #include "octeon_iq.h" @@ -40,7 +39,6 @@ MODULE_AUTHOR("Cavium Networks, <support@cavium.com>"); MODULE_DESCRIPTION("Cavium LiquidIO Intelligent Server Adapter Driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION(LIQUIDIO_VERSION); MODULE_FIRMWARE(LIO_FW_DIR LIO_FW_BASE_NAME LIO_210SV_NAME "_" LIO_FW_NAME_TYPE_NIC LIO_FW_NAME_SUFFIX); MODULE_FIRMWARE(LIO_FW_DIR LIO_FW_BASE_NAME LIO_210NV_NAME @@ -71,9 +69,9 @@ "Bitmask indicating which consoles have debug output redirected to syslog."); /** - * \brief determines if a given console has debug enabled. - * @param console console to check - * @returns 1 = enabled. 0 otherwise + * octeon_console_debug_enabled - determines if a given console has debug enabled. + * @console: console to check + * Return: 1 = enabled. 0 otherwise */ static int octeon_console_debug_enabled(u32 console) { @@ -97,14 +95,6 @@ struct lio_trusted_vf_ctx { struct completion complete; int status; -}; - -struct liquidio_rx_ctl_context { - int octeon_id; - - wait_queue_head_t wc; - - int cond; }; struct oct_link_status_resp { @@ -136,7 +126,7 @@ } s; }; -/** Octeon device properties to be used by the NIC module. +/* Octeon device properties to be used by the NIC module. * Each octeon device in the system will be represented * by this structure in the NIC module. */ @@ -171,13 +161,13 @@ static struct handshake handshake[MAX_OCTEON_DEVICES]; static struct completion first_stage; -static void octeon_droq_bh(unsigned long pdev) +static void octeon_droq_bh(struct tasklet_struct *t) { int q_no; int reschedule = 0; - struct octeon_device *oct = (struct octeon_device *)pdev; - struct octeon_device_priv *oct_priv = - (struct octeon_device_priv *)oct->priv; + struct octeon_device_priv *oct_priv = from_tasklet(oct_priv, t, + droq_tasklet); + struct octeon_device *oct = oct_priv->dev; for (q_no = 0; q_no < MAX_OCTEON_OUTPUT_QUEUES(oct); q_no++) { if (!(oct->io_qmask.oq & BIT_ULL(q_no))) @@ -232,8 +222,8 @@ } /** - * \brief Forces all IO queues off on a given device - * @param oct Pointer to Octeon device + * force_io_queues_off - Forces all IO queues off on a given device + * @oct: Pointer to Octeon device */ static void force_io_queues_off(struct octeon_device *oct) { @@ -248,8 +238,8 @@ } /** - * \brief Cause device to go quiet so it can be safely removed/reset/etc - * @param oct Pointer to Octeon device + * pcierror_quiesce_device - Cause device to go quiet so it can be safely removed/reset/etc + * @oct: Pointer to Octeon device */ static inline void pcierror_quiesce_device(struct octeon_device *oct) { @@ -293,8 +283,8 @@ } /** - * \brief Cleanup PCI AER uncorrectable error status - * @param dev Pointer to PCI device + * cleanup_aer_uncorrect_error_status - Cleanup PCI AER uncorrectable error status + * @dev: Pointer to PCI device */ static void cleanup_aer_uncorrect_error_status(struct pci_dev *dev) { @@ -313,8 +303,8 @@ } /** - * \brief Stop all PCI IO to a given device - * @param dev Pointer to Octeon device + * stop_pci_io - Stop all PCI IO to a given device + * @oct: Pointer to Octeon device */ static void stop_pci_io(struct octeon_device *oct) { @@ -342,9 +332,9 @@ } /** - * \brief called when PCI error is detected - * @param pdev Pointer to PCI device - * @param state The current pci connection state + * liquidio_pcie_error_detected - called when PCI error is detected + * @pdev: Pointer to PCI device + * @state: The current pci connection state * * This function is called after a PCI bus error affecting * this device has been detected. @@ -372,11 +362,10 @@ } /** - * \brief mmio handler - * @param pdev Pointer to PCI device + * liquidio_pcie_mmio_enabled - mmio handler + * @pdev: Pointer to PCI device */ -static pci_ers_result_t liquidio_pcie_mmio_enabled( - struct pci_dev *pdev __attribute__((unused))) +static pci_ers_result_t liquidio_pcie_mmio_enabled(struct pci_dev __maybe_unused *pdev) { /* We should never hit this since we never ask for a reset for a Fatal * Error. We always return DISCONNECT in io_error above. @@ -386,14 +375,13 @@ } /** - * \brief called after the pci bus has been reset. - * @param pdev Pointer to PCI device + * liquidio_pcie_slot_reset - called after the pci bus has been reset. + * @pdev: Pointer to PCI device * * Restart the card from scratch, as if from a cold-boot. Implementation * resembles the first-half of the octeon_resume routine. */ -static pci_ers_result_t liquidio_pcie_slot_reset( - struct pci_dev *pdev __attribute__((unused))) +static pci_ers_result_t liquidio_pcie_slot_reset(struct pci_dev __maybe_unused *pdev) { /* We should never hit this since we never ask for a reset for a Fatal * Error. We always return DISCONNECT in io_error above. @@ -403,39 +391,20 @@ } /** - * \brief called when traffic can start flowing again. - * @param pdev Pointer to PCI device + * liquidio_pcie_resume - called when traffic can start flowing again. + * @pdev: Pointer to PCI device * * This callback is called when the error recovery driver tells us that * its OK to resume normal operation. Implementation resembles the * second-half of the octeon_resume routine. */ -static void liquidio_pcie_resume(struct pci_dev *pdev __attribute__((unused))) +static void liquidio_pcie_resume(struct pci_dev __maybe_unused *pdev) { /* Nothing to be done here. */ } -#ifdef CONFIG_PM -/** - * \brief called when suspending - * @param pdev Pointer to PCI device - * @param state state to suspend to - */ -static int liquidio_suspend(struct pci_dev *pdev __attribute__((unused)), - pm_message_t state __attribute__((unused))) -{ - return 0; -} - -/** - * \brief called when resuming - * @param pdev Pointer to PCI device - */ -static int liquidio_resume(struct pci_dev *pdev __attribute__((unused))) -{ - return 0; -} -#endif +#define liquidio_suspend NULL +#define liquidio_resume NULL /* For PCI-E Advanced Error Recovery (AER) Interface */ static const struct pci_error_handlers liquidio_err_handler = { @@ -461,24 +430,22 @@ }; MODULE_DEVICE_TABLE(pci, liquidio_pci_tbl); +static SIMPLE_DEV_PM_OPS(liquidio_pm_ops, liquidio_suspend, liquidio_resume); + static struct pci_driver liquidio_pci_driver = { .name = "LiquidIO", .id_table = liquidio_pci_tbl, .probe = liquidio_probe, .remove = liquidio_remove, .err_handler = &liquidio_err_handler, /* For AER */ - -#ifdef CONFIG_PM - .suspend = liquidio_suspend, - .resume = liquidio_resume, -#endif + .driver.pm = &liquidio_pm_ops, #ifdef CONFIG_PCI_IOV .sriov_configure = liquidio_enable_sriov, #endif }; /** - * \brief register PCI driver + * liquidio_init_pci - register PCI driver */ static int liquidio_init_pci(void) { @@ -486,7 +453,7 @@ } /** - * \brief unregister PCI driver + * liquidio_deinit_pci - unregister PCI driver */ static void liquidio_deinit_pci(void) { @@ -494,9 +461,9 @@ } /** - * \brief Check Tx queue status, and take appropriate action - * @param lio per-network private data - * @returns 0 if full, number of queues woken up otherwise + * check_txq_status - Check Tx queue status, and take appropriate action + * @lio: per-network private data + * Return: 0 if full, number of queues woken up otherwise */ static inline int check_txq_status(struct lio *lio) { @@ -522,8 +489,8 @@ } /** - * \brief Print link information - * @param netdev network device + * print_link_info - Print link information + * @netdev: network device */ static void print_link_info(struct net_device *netdev) { @@ -544,8 +511,8 @@ } /** - * \brief Routine to notify MTU change - * @param work work_struct data structure + * octnet_link_status_change - Routine to notify MTU change + * @work: work_struct data structure */ static void octnet_link_status_change(struct work_struct *work) { @@ -562,8 +529,8 @@ } /** - * \brief Sets up the mtu status change work - * @param netdev network device + * setup_link_status_change_wq - Sets up the mtu status change work + * @netdev: network device */ static inline int setup_link_status_change_wq(struct net_device *netdev) { @@ -594,9 +561,9 @@ } /** - * \brief Update link status - * @param netdev network device - * @param ls link status structure + * update_link_status - Update link status + * @netdev: network device + * @ls: link status structure * * Called on receipt of a link status response from the core application to * update each interface's link status. @@ -642,26 +609,6 @@ } /** - * lio_sync_octeon_time_cb - callback that is invoked when soft command - * sent by lio_sync_octeon_time() has completed successfully or failed - * - * @oct - octeon device structure - * @status - indicates success or failure - * @buf - pointer to the command that was sent to firmware - **/ -static void lio_sync_octeon_time_cb(struct octeon_device *oct, - u32 status, void *buf) -{ - struct octeon_soft_command *sc = (struct octeon_soft_command *)buf; - - if (status) - dev_err(&oct->pci_dev->dev, - "Failed to sync time to octeon; error=%d\n", status); - - octeon_free_soft_command(oct, sc); -} - -/** * lio_sync_octeon_time - send latest localtime to octeon firmware so that * firmware will correct it's time, in case there is a time skew * @@ -677,7 +624,7 @@ struct lio_time *lt; int ret; - sc = octeon_alloc_soft_command(oct, sizeof(struct lio_time), 0, 0); + sc = octeon_alloc_soft_command(oct, sizeof(struct lio_time), 16, 0); if (!sc) { dev_err(&oct->pci_dev->dev, "Failed to sync time to octeon: soft command allocation failed\n"); @@ -696,15 +643,16 @@ octeon_prepare_soft_command(oct, sc, OPCODE_NIC, OPCODE_NIC_SYNC_OCTEON_TIME, 0, 0, 0); - sc->callback = lio_sync_octeon_time_cb; - sc->callback_arg = sc; - sc->wait_time = 1000; + init_completion(&sc->complete); + sc->sc_status = OCTEON_REQUEST_PENDING; ret = octeon_send_soft_command(oct, sc); if (ret == IQ_SEND_FAILED) { dev_err(&oct->pci_dev->dev, "Failed to sync time to octeon: failed to send soft command\n"); octeon_free_soft_command(oct, sc); + } else { + WRITE_ONCE(sc->caller_is_done, true); } queue_delayed_work(lio->sync_octeon_time_wq.wq, @@ -713,10 +661,9 @@ } /** - * setup_sync_octeon_time_wq - Sets up the work to periodically update - * local time to octeon firmware + * setup_sync_octeon_time_wq - prepare work to periodically update local time to octeon firmware * - * @netdev - network device which should send time update to firmware + * @netdev: network device which should send time update to firmware **/ static inline int setup_sync_octeon_time_wq(struct net_device *netdev) { @@ -740,10 +687,12 @@ } /** - * cleanup_sync_octeon_time_wq - stop scheduling and destroy the work created - * to periodically update local time to octeon firmware + * cleanup_sync_octeon_time_wq - destroy wq * - * @netdev - network device which should send time update to firmware + * @netdev: network device which should send time update to firmware + * + * Stop scheduling and destroy the work created to periodically update local + * time to octeon firmware. **/ static inline void cleanup_sync_octeon_time_wq(struct net_device *netdev) { @@ -878,13 +827,12 @@ } /** - * \brief PCI probe handler - * @param pdev PCI device structure - * @param ent unused + * liquidio_probe - PCI probe handler + * @pdev: PCI device structure + * @ent: unused */ static int -liquidio_probe(struct pci_dev *pdev, - const struct pci_device_id *ent __attribute__((unused))) +liquidio_probe(struct pci_dev *pdev, const struct pci_device_id __maybe_unused *ent) { struct octeon_device *oct_dev = NULL; struct handshake *hs; @@ -974,8 +922,8 @@ } /** - * \brief PCI FLR for each Octeon device. - * @param oct octeon device + * octeon_pci_flr - PCI FLR for each Octeon device. + * @oct: octeon device */ static void octeon_pci_flr(struct octeon_device *oct) { @@ -1001,9 +949,8 @@ } /** - *\brief Destroy resources associated with octeon device - * @param pdev PCI device structure - * @param ent unused + * octeon_destroy_resources - Destroy resources associated with octeon device + * @oct: octeon device */ static void octeon_destroy_resources(struct octeon_device *oct) { @@ -1027,21 +974,20 @@ schedule_timeout_uninterruptible(HZ / 10); - /* fallthrough */ + fallthrough; case OCT_DEV_HOST_OK: - /* fallthrough */ case OCT_DEV_CONSOLE_INIT_DONE: /* Remove any consoles */ octeon_remove_consoles(oct); - /* fallthrough */ + fallthrough; case OCT_DEV_IO_QUEUES_DONE: - if (wait_for_pending_requests(oct)) - dev_err(&oct->pci_dev->dev, "There were pending requests\n"); - if (lio_wait_for_instr_fetch(oct)) dev_err(&oct->pci_dev->dev, "IQ had pending instructions\n"); + + if (wait_for_pending_requests(oct)) + dev_err(&oct->pci_dev->dev, "There were pending requests\n"); /* Disable the input and output queues now. No more packets will * arrive from Octeon, but we should wait for all packet @@ -1052,7 +998,32 @@ if (lio_wait_for_oq_pkts(oct)) dev_err(&oct->pci_dev->dev, "OQ had pending packets\n"); - /* fallthrough */ + /* Force all requests waiting to be fetched by OCTEON to + * complete. + */ + for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) { + struct octeon_instr_queue *iq; + + if (!(oct->io_qmask.iq & BIT_ULL(i))) + continue; + iq = oct->instr_queue[i]; + + if (atomic_read(&iq->instr_pending)) { + spin_lock_bh(&iq->lock); + iq->fill_cnt = 0; + iq->octeon_read_index = iq->host_write_index; + iq->stats.instr_processed += + atomic_read(&iq->instr_pending); + lio_process_iq_request_list(oct, iq, 0); + spin_unlock_bh(&iq->lock); + } + } + + lio_process_ordered_list(oct, 1); + octeon_free_sc_done_list(oct); + octeon_free_sc_zombie_list(oct); + + fallthrough; case OCT_DEV_INTR_SET_DONE: /* Disable interrupts */ oct->fn_list.disable_interrupt(oct, OCTEON_ALL_INTR); @@ -1087,17 +1058,17 @@ kfree(oct->irq_name_storage); oct->irq_name_storage = NULL; - /* fallthrough */ + fallthrough; case OCT_DEV_MSIX_ALLOC_VECTOR_DONE: if (OCTEON_CN23XX_PF(oct)) octeon_free_ioq_vector(oct); - /* fallthrough */ + fallthrough; case OCT_DEV_MBOX_SETUP_DONE: if (OCTEON_CN23XX_PF(oct)) oct->fn_list.free_mbox(oct); - /* fallthrough */ + fallthrough; case OCT_DEV_IN_RESET: case OCT_DEV_DROQ_INIT_DONE: /* Wait for any pending operations */ @@ -1120,11 +1091,11 @@ } } - /* fallthrough */ + fallthrough; case OCT_DEV_RESP_LIST_INIT_DONE: octeon_delete_response_list(oct); - /* fallthrough */ + fallthrough; case OCT_DEV_INSTR_QUEUE_INIT_DONE: for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) { if (!(oct->io_qmask.iq & BIT_ULL(i))) @@ -1135,16 +1106,16 @@ if (oct->sriov_info.sriov_enabled) pci_disable_sriov(oct->pci_dev); #endif - /* fallthrough */ + fallthrough; case OCT_DEV_SC_BUFF_POOL_INIT_DONE: octeon_free_sc_buffer_pool(oct); - /* fallthrough */ + fallthrough; case OCT_DEV_DISPATCH_INIT_DONE: octeon_delete_dispatch_list(oct); cancel_delayed_work_sync(&oct->nic_poll_work.work); - /* fallthrough */ + fallthrough; case OCT_DEV_PCI_MAP_DONE: refcount = octeon_deregister_device(oct); @@ -1162,13 +1133,13 @@ octeon_unmap_pci_barx(oct, 0); octeon_unmap_pci_barx(oct, 1); - /* fallthrough */ + fallthrough; case OCT_DEV_PCI_ENABLE_DONE: pci_clear_master(oct->pci_dev); /* Disable the device, releasing the PCI INT */ pci_disable_device(oct->pci_dev); - /* fallthrough */ + fallthrough; case OCT_DEV_BEGIN_STATE: /* Nothing to be done here either */ break; @@ -1178,60 +1149,30 @@ } /** - * \brief Callback for rx ctrl - * @param status status of request - * @param buf pointer to resp structure + * send_rx_ctrl_cmd - Send Rx control command + * @lio: per-network private data + * @start_stop: whether to start or stop */ -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 - * @param start_stop whether to start or stop - */ -static void send_rx_ctrl_cmd(struct lio *lio, int start_stop) +static int send_rx_ctrl_cmd(struct lio *lio, int start_stop) { 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; if (oct->props[lio->ifidx].rx_on == start_stop) - return; + return 0; sc = (struct octeon_soft_command *) octeon_alloc_soft_command(oct, OCTNET_CMD_SIZE, - 16, ctx_size); + 16, 0); + if (!sc) { + netif_info(lio, rx_err, lio->netdev, + "Failed to allocate octeon_soft_command struct\n"); + return -ENOMEM; + } 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; @@ -1244,29 +1185,32 @@ 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; + init_completion(&sc->complete); + sc->sc_status = OCTEON_REQUEST_PENDING; 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"); + octeon_free_soft_command(oct, sc); } 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; + retval = wait_for_sc_completion_timeout(oct, sc, 0); + if (retval) + return retval; + oct->props[lio->ifidx].rx_on = start_stop; + WRITE_ONCE(sc->caller_is_done, true); } - octeon_free_soft_command(oct, sc); + return retval; } /** - * \brief Destroy NIC device interface - * @param oct octeon device - * @param ifidx which interface to destroy + * liquidio_destroy_nic_device - Destroy NIC device interface + * @oct: octeon device + * @ifidx: which interface to destroy * * Cleanup associated with each interface for an Octeon device when NIC * module is being unloaded or if initialization fails during load. @@ -1274,8 +1218,10 @@ static void liquidio_destroy_nic_device(struct octeon_device *oct, int ifidx) { struct net_device *netdev = oct->props[ifidx].netdev; - struct lio *lio; + struct octeon_device_priv *oct_priv = + (struct octeon_device_priv *)oct->priv; struct napi_struct *napi, *n; + struct lio *lio; if (!netdev) { dev_err(&oct->pci_dev->dev, "%s No netdevice ptr for index %d\n", @@ -1304,6 +1250,8 @@ list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list) netif_napi_del(napi); + tasklet_enable(&oct_priv->droq_tasklet); + if (atomic_read(&lio->ifstate) & LIO_IFSTATE_REGISTERED) unregister_netdev(netdev); @@ -1322,8 +1270,8 @@ } /** - * \brief Stop complete NIC functionality - * @param oct octeon device + * liquidio_stop_nic_module - Stop complete NIC functionality + * @oct: octeon device */ static int liquidio_stop_nic_module(struct octeon_device *oct) { @@ -1363,8 +1311,8 @@ } /** - * \brief Cleans up resources at unload time - * @param pdev PCI device structure + * liquidio_remove - Cleans up resources at unload time + * @pdev: PCI device structure */ static void liquidio_remove(struct pci_dev *pdev) { @@ -1396,14 +1344,13 @@ } /** - * \brief Identify the Octeon device and to map the BAR address space - * @param oct octeon device + * octeon_chip_specific_setup - Identify the Octeon device and to map the BAR address space + * @oct: octeon device */ static int octeon_chip_specific_setup(struct octeon_device *oct) { u32 dev_id, rev_id; int ret = 1; - char *s; pci_read_config_dword(oct->pci_dev, 0, &dev_id); pci_read_config_dword(oct->pci_dev, 8, &rev_id); @@ -1413,13 +1360,11 @@ case OCTEON_CN68XX_PCIID: oct->chip_id = OCTEON_CN68XX; ret = lio_setup_cn68xx_octeon_device(oct); - s = "CN68XX"; break; case OCTEON_CN66XX_PCIID: oct->chip_id = OCTEON_CN66XX; ret = lio_setup_cn66xx_octeon_device(oct); - s = "CN66XX"; break; case OCTEON_CN23XX_PCIID_PF: @@ -1432,28 +1377,19 @@ pci_sriov_set_totalvfs(oct->pci_dev, oct->sriov_info.max_vfs); #endif - s = "CN23XX"; break; default: - s = "?"; dev_err(&oct->pci_dev->dev, "Unknown device found (dev_id: %x)\n", dev_id); } - - if (!ret) - dev_info(&oct->pci_dev->dev, "%s PASS%d.%d %s Version: %s\n", s, - OCTEON_MAJOR_REV(oct), - OCTEON_MINOR_REV(oct), - octeon_get_conf(oct)->card_name, - LIQUIDIO_VERSION); return ret; } /** - * \brief PCI initialization for each Octeon device. - * @param oct octeon device + * octeon_pci_os_setup - PCI initialization for each Octeon device. + * @oct: octeon device */ static int octeon_pci_os_setup(struct octeon_device *oct) { @@ -1476,8 +1412,8 @@ } /** - * \brief Unmap and free network buffer - * @param buf buffer + * free_netbuf - Unmap and free network buffer + * @buf: buffer */ static void free_netbuf(void *buf) { @@ -1496,8 +1432,8 @@ } /** - * \brief Unmap and free gather buffer - * @param buf buffer + * free_netsgbuf - Unmap and free gather buffer + * @buf: buffer */ static void free_netsgbuf(void *buf) { @@ -1519,11 +1455,11 @@ i = 1; while (frags--) { - struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i - 1]; + skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1]; pci_unmap_page((lio->oct_dev)->pci_dev, g->sg[(i >> 2)].ptr[(i & 3)], - frag->size, DMA_TO_DEVICE); + skb_frag_size(frag), DMA_TO_DEVICE); i++; } @@ -1536,8 +1472,8 @@ } /** - * \brief Unmap and free gather buffer with response - * @param buf buffer + * free_netsgbuf_with_resp - Unmap and free gather buffer with response + * @buf: buffer */ static void free_netsgbuf_with_resp(void *buf) { @@ -1562,11 +1498,11 @@ i = 1; while (frags--) { - struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i - 1]; + skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1]; pci_unmap_page((lio->oct_dev)->pci_dev, g->sg[(i >> 2)].ptr[(i & 3)], - frag->size, DMA_TO_DEVICE); + skb_frag_size(frag), DMA_TO_DEVICE); i++; } @@ -1580,9 +1516,9 @@ } /** - * \brief Adjust ptp frequency - * @param ptp PTP clock info - * @param ppb how much to adjust by, in parts-per-billion + * liquidio_ptp_adjfreq - Adjust ptp frequency + * @ptp: PTP clock info + * @ppb: how much to adjust by, in parts-per-billion */ static int liquidio_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb) { @@ -1617,9 +1553,9 @@ } /** - * \brief Adjust ptp time - * @param ptp PTP clock info - * @param delta how much to adjust by, in nanosecs + * liquidio_ptp_adjtime - Adjust ptp time + * @ptp: PTP clock info + * @delta: how much to adjust by, in nanosecs */ static int liquidio_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) { @@ -1634,9 +1570,9 @@ } /** - * \brief Get hardware clock time, including any adjustment - * @param ptp PTP clock info - * @param ts timespec + * liquidio_ptp_gettime - Get hardware clock time, including any adjustment + * @ptp: PTP clock info + * @ts: timespec */ static int liquidio_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) @@ -1657,9 +1593,9 @@ } /** - * \brief Set hardware clock time. Reset adjustment - * @param ptp PTP clock info - * @param ts timespec + * liquidio_ptp_settime - Set hardware clock time. Reset adjustment + * @ptp: PTP clock info + * @ts: timespec */ static int liquidio_ptp_settime(struct ptp_clock_info *ptp, const struct timespec64 *ts) @@ -1680,22 +1616,22 @@ } /** - * \brief Check if PTP is enabled - * @param ptp PTP clock info - * @param rq request - * @param on is it on + * liquidio_ptp_enable - Check if PTP is enabled + * @ptp: PTP clock info + * @rq: request + * @on: is it on */ static int -liquidio_ptp_enable(struct ptp_clock_info *ptp __attribute__((unused)), - struct ptp_clock_request *rq __attribute__((unused)), - int on __attribute__((unused))) +liquidio_ptp_enable(struct ptp_clock_info __maybe_unused *ptp, + struct ptp_clock_request __maybe_unused *rq, + int __maybe_unused on) { return -EOPNOTSUPP; } /** - * \brief Open PTP clock source - * @param netdev network device + * oct_ptp_open - Open PTP clock source + * @netdev: network device */ static void oct_ptp_open(struct net_device *netdev) { @@ -1727,8 +1663,8 @@ } /** - * \brief Init PTP clock - * @param oct octeon device + * liquidio_ptp_init - Init PTP clock + * @oct: octeon device */ static void liquidio_ptp_init(struct octeon_device *oct) { @@ -1744,8 +1680,8 @@ } /** - * \brief Load firmware to device - * @param oct octeon device + * load_firmware - Load firmware to device + * @oct: octeon device * * Maps device to firmware filename, requests firmware, and downloads it */ @@ -1783,8 +1719,8 @@ } /** - * \brief Poll routine for checking transmit queue status - * @param work work_struct data structure + * octnet_poll_check_txq_status - Poll routine for checking transmit queue status + * @work: work_struct data structure */ static void octnet_poll_check_txq_status(struct work_struct *work) { @@ -1800,8 +1736,8 @@ } /** - * \brief Sets up the txq poll check - * @param netdev network device + * setup_tx_poll_fn - Sets up the txq poll check + * @netdev: network device */ static inline int setup_tx_poll_fn(struct net_device *netdev) { @@ -1833,16 +1769,21 @@ } /** - * \brief Net device open for LiquidIO - * @param netdev network device + * liquidio_open - Net device open for LiquidIO + * @netdev: network device */ static int liquidio_open(struct net_device *netdev) { struct lio *lio = GET_LIO(netdev); struct octeon_device *oct = lio->oct_dev; + struct octeon_device_priv *oct_priv = + (struct octeon_device_priv *)oct->priv; struct napi_struct *napi, *n; + int ret = 0; if (oct->props[lio->ifidx].napi_enabled == 0) { + tasklet_disable(&oct_priv->droq_tasklet); + list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list) napi_enable(napi); @@ -1857,13 +1798,10 @@ ifstate_set(lio, LIO_IFSTATE_RUNNING); - if (OCTEON_CN23XX_PF(oct)) { - if (!oct->msix_on) - if (setup_tx_poll_fn(netdev)) - return -1; - } else { - if (setup_tx_poll_fn(netdev)) - return -1; + if (!OCTEON_CN23XX_PF(oct) || !oct->msix_on) { + ret = setup_tx_poll_fn(netdev); + if (ret) + goto err_poll; } netif_tx_start_all_queues(netdev); @@ -1874,23 +1812,55 @@ 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); + ret = send_rx_ctrl_cmd(lio, 1); + if (ret) + goto err_rx_ctrl; + + /* start periodical statistics fetch */ + INIT_DELAYED_WORK(&lio->stats_wk.work, lio_fetch_stats); + lio->stats_wk.ctxptr = lio; + schedule_delayed_work(&lio->stats_wk.work, msecs_to_jiffies + (LIQUIDIO_NDEV_STATS_POLL_TIME_MS)); dev_info(&oct->pci_dev->dev, "%s interface is opened\n", netdev->name); return 0; + +err_rx_ctrl: + if (!OCTEON_CN23XX_PF(oct) || !oct->msix_on) + cleanup_tx_poll_fn(netdev); +err_poll: + if (lio->ptp_clock) { + ptp_clock_unregister(lio->ptp_clock); + lio->ptp_clock = NULL; + } + + 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; + } + + return ret; } /** - * \brief Net device stop for LiquidIO - * @param netdev network device + * liquidio_stop - Net device stop for LiquidIO + * @netdev: network device */ static int liquidio_stop(struct net_device *netdev) { struct lio *lio = GET_LIO(netdev); struct octeon_device *oct = lio->oct_dev; + struct octeon_device_priv *oct_priv = + (struct octeon_device_priv *)oct->priv; struct napi_struct *napi, *n; + int ret = 0; ifstate_reset(lio, LIO_IFSTATE_RUNNING); @@ -1907,7 +1877,9 @@ lio->link_changes++; /* Tell Octeon that nic interface is down. */ - send_rx_ctrl_cmd(lio, 0); + ret = send_rx_ctrl_cmd(lio, 0); + if (ret) + return ret; if (OCTEON_CN23XX_PF(oct)) { if (!oct->msix_on) @@ -1915,6 +1887,8 @@ } else { cleanup_tx_poll_fn(netdev); } + + cancel_delayed_work_sync(&lio->stats_wk.work); if (lio->ptp_clock) { ptp_clock_unregister(lio->ptp_clock); @@ -1934,16 +1908,18 @@ if (OCTEON_CN23XX_PF(oct)) oct->droq[0]->ops.poll_mode = 0; + + tasklet_enable(&oct_priv->droq_tasklet); } dev_info(&oct->pci_dev->dev, "%s interface is stopped\n", netdev->name); - return 0; + return ret; } /** - * \brief Converts a mask based on net device flags - * @param netdev network device + * get_new_flags - Converts a mask based on net device flags + * @netdev: network device * * This routine generates a octnet_ifflags mask from the net device flags * received from the OS. @@ -1975,8 +1951,8 @@ } /** - * \brief Net device set_multicast_list - * @param netdev network device + * liquidio_set_mcast_list - Net device set_multicast_list + * @netdev: network device */ static void liquidio_set_mcast_list(struct net_device *netdev) { @@ -2014,18 +1990,18 @@ /* Apparently, any activity in this call from the kernel has to * be atomic. So we won't wait for response. */ - nctrl.wait_time = 0; ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl); - if (ret < 0) { + if (ret) { dev_err(&oct->pci_dev->dev, "DEVFLAGS change failed in core (ret: 0x%x)\n", ret); } } /** - * \brief Net device set_mac_address - * @param netdev network device + * liquidio_set_mac - Net device set_mac_address + * @netdev: network device + * @p: pointer to sockaddr */ static int liquidio_set_mac(struct net_device *netdev, void *p) { @@ -2046,8 +2022,6 @@ nctrl.ncmd.s.more = 1; nctrl.iq_no = lio->linfo.txpciq[0].s.q_no; nctrl.netpndev = (u64)netdev; - nctrl.cb_fn = liquidio_link_ctrl_cmd_completion; - nctrl.wait_time = 100; nctrl.udd[0] = 0; /* The MAC Address is presented in network byte order. */ @@ -2058,6 +2032,14 @@ dev_err(&oct->pci_dev->dev, "MAC Address change failed\n"); return -ENOMEM; } + + if (nctrl.sc_status) { + dev_err(&oct->pci_dev->dev, + "%s: MAC Address change failed. sc return=%x\n", + __func__, nctrl.sc_status); + return -EIO; + } + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); memcpy(((u8 *)&lio->linfo.hw_addr) + 2, addr->sa_data, ETH_ALEN); @@ -2111,7 +2093,6 @@ lstats->rx_packets = pkts; lstats->rx_dropped = drop; - octnet_get_link_stats(netdev); lstats->multicast = oct->link_stats.fromwire.fw_total_mcast; lstats->collisions = oct->link_stats.fromhost.total_collisions; @@ -2138,10 +2119,9 @@ } /** - * \brief Handler for SIOCSHWTSTAMP ioctl - * @param netdev network device - * @param ifr interface request - * @param cmd command + * hwtstamp_ioctl - Handler for SIOCSHWTSTAMP ioctl + * @netdev: network device + * @ifr: interface request */ static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr) { @@ -2196,10 +2176,10 @@ } /** - * \brief ioctl handler - * @param netdev network device - * @param ifr interface request - * @param cmd command + * liquidio_ioctl - ioctl handler + * @netdev: network device + * @ifr: interface request + * @cmd: command */ static int liquidio_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { @@ -2209,16 +2189,17 @@ case SIOCSHWTSTAMP: if (lio->oct_dev->ptp_enable) return hwtstamp_ioctl(netdev, ifr); - /* fall through */ + fallthrough; default: return -EOPNOTSUPP; } } /** - * \brief handle a Tx timestamp response - * @param status response status - * @param buf pointer to skb + * handle_timestamp - handle a Tx timestamp response + * @oct: octeon device + * @status: response status + * @buf: pointer to skb */ static void handle_timestamp(struct octeon_device *oct, u32 status, @@ -2259,10 +2240,12 @@ tx_buffer_free(skb); } -/* \brief Send a data packet that will be timestamped - * @param oct octeon device - * @param ndata pointer to network data - * @param finfo pointer to private network data +/** + * send_nic_timestamp_pkt - Send a data packet that will be timestamped + * @oct: octeon device + * @ndata: pointer to network data + * @finfo: pointer to private network data + * @xmit_more: more is coming */ static inline int send_nic_timestamp_pkt(struct octeon_device *oct, struct octnic_data_pkt *ndata, @@ -2318,10 +2301,12 @@ return retval; } -/** \brief Transmit networks packets to the Octeon interface - * @param skbuff skbuff struct to be passed to network layer. - * @param netdev pointer to network device - * @returns whether the packet was transmitted to the device okay or not +/** + * liquidio_xmit - Transmit networks packets to the Octeon interface + * @skb: skbuff struct to be passed to network layer. + * @netdev: pointer to network device + * + * Return: whether the packet was transmitted to the device okay or not * (NETDEV_TX_OK or NETDEV_TX_BUSY) */ static netdev_tx_t liquidio_xmit(struct sk_buff *skb, struct net_device *netdev) @@ -2431,7 +2416,7 @@ } else { int i, frags; - struct skb_frag_struct *frag; + skb_frag_t *frag; struct octnic_gather *g; spin_lock(&lio->glist_lock[q_idx]); @@ -2469,11 +2454,9 @@ frag = &skb_shinfo(skb)->frags[i - 1]; g->sg[(i >> 2)].ptr[(i & 3)] = - dma_map_page(&oct->pci_dev->dev, - frag->page.p, - frag->page_offset, - frag->size, - DMA_TO_DEVICE); + skb_frag_dma_map(&oct->pci_dev->dev, + frag, 0, skb_frag_size(frag), + DMA_TO_DEVICE); if (dma_mapping_error(&oct->pci_dev->dev, g->sg[i >> 2].ptr[i & 3])) { @@ -2485,7 +2468,7 @@ frag = &skb_shinfo(skb)->frags[j - 1]; dma_unmap_page(&oct->pci_dev->dev, g->sg[j >> 2].ptr[j & 3], - frag->size, + skb_frag_size(frag), DMA_TO_DEVICE); } dev_err(&oct->pci_dev->dev, "%s DMA mapping error 3\n", @@ -2493,7 +2476,8 @@ return NETDEV_TX_BUSY; } - add_sg_size(&g->sg[(i >> 2)], frag->size, (i & 3)); + add_sg_size(&g->sg[(i >> 2)], skb_frag_size(frag), + (i & 3)); i++; } @@ -2529,7 +2513,7 @@ irh->vlan = skb_vlan_tag_get(skb) & 0xfff; } - xmit_more = skb->xmit_more; + xmit_more = netdev_xmit_more(); if (unlikely(cmdsetup.s.timestamp)) status = send_nic_timestamp_pkt(oct, &ndata, finfo, xmit_more); @@ -2567,10 +2551,12 @@ return NETDEV_TX_OK; } -/** \brief Network device Tx timeout - * @param netdev pointer to network device +/** + * liquidio_tx_timeout - Network device Tx timeout + * @netdev: pointer to network device + * @txqueue: index of the hung transmit queue */ -static void liquidio_tx_timeout(struct net_device *netdev) +static void liquidio_tx_timeout(struct net_device *netdev, unsigned int txqueue) { struct lio *lio; @@ -2598,14 +2584,15 @@ nctrl.ncmd.s.cmd = OCTNET_CMD_ADD_VLAN_FILTER; nctrl.ncmd.s.param1 = vid; 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) { + if (ret) { dev_err(&oct->pci_dev->dev, "Add VLAN filter failed in core (ret: 0x%x)\n", ret); + if (ret > 0) + ret = -EIO; } return ret; @@ -2626,24 +2613,25 @@ nctrl.ncmd.s.cmd = OCTNET_CMD_DEL_VLAN_FILTER; nctrl.ncmd.s.param1 = vid; 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) { + if (ret) { dev_err(&oct->pci_dev->dev, "Del VLAN filter failed in core (ret: 0x%x)\n", ret); + if (ret > 0) + ret = -EIO; } return ret; } -/** Sending command to enable/disable RX checksum offload - * @param netdev pointer to network device - * @param command OCTNET_CMD_TNL_RX_CSUM_CTL - * @param rx_cmd_bit OCTNET_CMD_RXCSUM_ENABLE/ - * OCTNET_CMD_RXCSUM_DISABLE - * @returns SUCCESS or FAILURE +/** + * liquidio_set_rxcsum_command - Sending command to enable/disable RX checksum offload + * @netdev: pointer to network device + * @command: OCTNET_CMD_TNL_RX_CSUM_CTL + * @rx_cmd: OCTNET_CMD_RXCSUM_ENABLE/OCTNET_CMD_RXCSUM_DISABLE + * Returns: SUCCESS or FAILURE */ static int liquidio_set_rxcsum_command(struct net_device *netdev, int command, u8 rx_cmd) @@ -2659,26 +2647,28 @@ nctrl.ncmd.s.cmd = command; nctrl.ncmd.s.param1 = rx_cmd; 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) { + if (ret) { dev_err(&oct->pci_dev->dev, "DEVFLAGS RXCSUM change failed in core(ret:0x%x)\n", ret); + if (ret > 0) + ret = -EIO; } return ret; } -/** Sending command to add/delete VxLAN UDP port to firmware - * @param netdev pointer to network device - * @param command OCTNET_CMD_VXLAN_PORT_CONFIG - * @param vxlan_port VxLAN port to be added or deleted - * @param vxlan_cmd_bit OCTNET_CMD_VXLAN_PORT_ADD, +/** + * liquidio_vxlan_port_command - Sending command to add/delete VxLAN UDP port to firmware + * @netdev: pointer to network device + * @command: OCTNET_CMD_VXLAN_PORT_CONFIG + * @vxlan_port: VxLAN port to be added or deleted + * @vxlan_cmd_bit: OCTNET_CMD_VXLAN_PORT_ADD, * OCTNET_CMD_VXLAN_PORT_DEL - * @returns SUCCESS or FAILURE + * Return: SUCCESS or FAILURE */ static int liquidio_vxlan_port_command(struct net_device *netdev, int command, u16 vxlan_port, u8 vxlan_cmd_bit) @@ -2695,23 +2685,54 @@ nctrl.ncmd.s.more = vxlan_cmd_bit; nctrl.ncmd.s.param1 = vxlan_port; 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) { + if (ret) { dev_err(&oct->pci_dev->dev, "VxLAN port add/delete failed in core (ret:0x%x)\n", ret); + if (ret > 0) + ret = -EIO; } return ret; } -/** \brief Net device fix features - * @param netdev pointer to network device - * @param request features requested - * @returns updated features list +static int liquidio_udp_tunnel_set_port(struct net_device *netdev, + unsigned int table, unsigned int entry, + struct udp_tunnel_info *ti) +{ + return liquidio_vxlan_port_command(netdev, + OCTNET_CMD_VXLAN_PORT_CONFIG, + htons(ti->port), + OCTNET_CMD_VXLAN_PORT_ADD); +} + +static int liquidio_udp_tunnel_unset_port(struct net_device *netdev, + unsigned int table, + unsigned int entry, + struct udp_tunnel_info *ti) +{ + return liquidio_vxlan_port_command(netdev, + OCTNET_CMD_VXLAN_PORT_CONFIG, + htons(ti->port), + OCTNET_CMD_VXLAN_PORT_DEL); +} + +static const struct udp_tunnel_nic_info liquidio_udp_tunnels = { + .set_port = liquidio_udp_tunnel_set_port, + .unset_port = liquidio_udp_tunnel_unset_port, + .tables = { + { .n_entries = 1024, .tunnel_types = UDP_TUNNEL_TYPE_VXLAN, }, + }, +}; + +/** + * liquidio_fix_features - Net device fix features + * @netdev: pointer to network device + * @request: features requested + * Return: updated features list */ static netdev_features_t liquidio_fix_features(struct net_device *netdev, netdev_features_t request) @@ -2747,9 +2768,10 @@ return request; } -/** \brief Net device set features - * @param netdev pointer to network device - * @param features features to enable/disable +/** + * liquidio_set_features - Net device set features + * @netdev: pointer to network device + * @features: features to enable/disable */ static int liquidio_set_features(struct net_device *netdev, netdev_features_t features) @@ -2796,36 +2818,13 @@ return 0; } -static void liquidio_add_vxlan_port(struct net_device *netdev, - struct udp_tunnel_info *ti) -{ - if (ti->type != UDP_TUNNEL_TYPE_VXLAN) - return; - - liquidio_vxlan_port_command(netdev, - OCTNET_CMD_VXLAN_PORT_CONFIG, - htons(ti->port), - OCTNET_CMD_VXLAN_PORT_ADD); -} - -static void liquidio_del_vxlan_port(struct net_device *netdev, - struct udp_tunnel_info *ti) -{ - if (ti->type != UDP_TUNNEL_TYPE_VXLAN) - return; - - liquidio_vxlan_port_command(netdev, - OCTNET_CMD_VXLAN_PORT_CONFIG, - htons(ti->port), - OCTNET_CMD_VXLAN_PORT_DEL); -} - static int __liquidio_set_vf_mac(struct net_device *netdev, int vfidx, u8 *mac, bool is_admin_assigned) { struct lio *lio = GET_LIO(netdev); struct octeon_device *oct = lio->oct_dev; struct octnic_ctrl_pkt nctrl; + int ret = 0; if (!is_valid_ether_addr(mac)) return -EINVAL; @@ -2839,12 +2838,13 @@ nctrl.ncmd.s.cmd = OCTNET_CMD_CHANGE_MACADDR; /* vfidx is 0 based, but vf_num (param1) is 1 based */ nctrl.ncmd.s.param1 = vfidx + 1; - nctrl.ncmd.s.param2 = (is_admin_assigned ? 1 : 0); nctrl.ncmd.s.more = 1; nctrl.iq_no = lio->linfo.txpciq[0].s.q_no; nctrl.netpndev = (u64)netdev; - nctrl.cb_fn = liquidio_link_ctrl_cmd_completion; - nctrl.wait_time = LIO_CMD_WAIT_TM; + if (is_admin_assigned) { + nctrl.ncmd.s.param2 = true; + nctrl.cb_fn = liquidio_link_ctrl_cmd_completion; + } nctrl.udd[0] = 0; /* The MAC Address is presented in network byte order. */ @@ -2852,9 +2852,11 @@ oct->sriov_info.vf_macaddr[vfidx] = nctrl.udd[0]; - octnet_send_nic_ctrl_pkt(oct, &nctrl); + ret = octnet_send_nic_ctrl_pkt(oct, &nctrl); + if (ret > 0) + ret = -EIO; - return 0; + return ret; } static int liquidio_set_vf_mac(struct net_device *netdev, int vfidx, u8 *mac) @@ -2873,6 +2875,62 @@ return retval; } +static int liquidio_set_vf_spoofchk(struct net_device *netdev, int vfidx, + bool enable) +{ + struct lio *lio = GET_LIO(netdev); + struct octeon_device *oct = lio->oct_dev; + struct octnic_ctrl_pkt nctrl; + int retval; + + if (!(oct->fw_info.app_cap_flags & LIQUIDIO_SPOOFCHK_CAP)) { + netif_info(lio, drv, lio->netdev, + "firmware does not support spoofchk\n"); + 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 (enable) { + if (oct->sriov_info.vf_spoofchk[vfidx]) + return 0; + } else { + /* Clear */ + if (!oct->sriov_info.vf_spoofchk[vfidx]) + return 0; + } + + memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt)); + nctrl.ncmd.s.cmdgroup = OCTNET_CMD_GROUP1; + nctrl.ncmd.s.cmd = OCTNET_CMD_SET_VF_SPOOFCHK; + nctrl.ncmd.s.param1 = + vfidx + 1; /* vfidx is 0 based, + * but vf_num (param1) is 1 based + */ + nctrl.ncmd.s.param2 = enable; + nctrl.ncmd.s.more = 0; + nctrl.iq_no = lio->linfo.txpciq[0].s.q_no; + nctrl.cb_fn = NULL; + + retval = octnet_send_nic_ctrl_pkt(oct, &nctrl); + + if (retval) { + netif_info(lio, drv, lio->netdev, + "Failed to set VF %d spoofchk %s\n", vfidx, + enable ? "on" : "off"); + return -1; + } + + oct->sriov_info.vf_spoofchk[vfidx] = enable; + netif_info(lio, drv, lio->netdev, "VF %u spoofchk is %s\n", vfidx, + enable ? "on" : "off"); + + return 0; +} + static int liquidio_set_vf_vlan(struct net_device *netdev, int vfidx, u16 vlan, u8 qos, __be16 vlan_proto) { @@ -2880,6 +2938,7 @@ struct octeon_device *oct = lio->oct_dev; struct octnic_ctrl_pkt nctrl; u16 vlantci; + int ret = 0; if (vfidx < 0 || vfidx >= oct->sriov_info.num_vfs_alloced) return -EINVAL; @@ -2911,13 +2970,17 @@ nctrl.ncmd.s.more = 0; nctrl.iq_no = lio->linfo.txpciq[0].s.q_no; nctrl.cb_fn = NULL; - nctrl.wait_time = LIO_CMD_WAIT_TM; - octnet_send_nic_ctrl_pkt(oct, &nctrl); + ret = octnet_send_nic_ctrl_pkt(oct, &nctrl); + if (ret) { + if (ret > 0) + ret = -EIO; + return ret; + } oct->sriov_info.vf_vlantci[vfidx] = vlantci; - return 0; + return ret; } static int liquidio_get_vf_config(struct net_device *netdev, int vfidx, @@ -2930,6 +2993,8 @@ if (vfidx < 0 || vfidx >= oct->sriov_info.num_vfs_alloced) return -EINVAL; + memset(ivi, 0, sizeof(struct ifla_vf_info)); + ivi->vf = vfidx; macaddr = 2 + (u8 *)&oct->sriov_info.vf_macaddr[vfidx]; ether_addr_copy(&ivi->mac[0], macaddr); @@ -2941,33 +3006,22 @@ else ivi->trusted = false; ivi->linkstate = oct->sriov_info.vf_linkstate[vfidx]; + ivi->spoofchk = oct->sriov_info.vf_spoofchk[vfidx]; + ivi->max_tx_rate = lio->linfo.link.s.speed; + ivi->min_tx_rate = 0; + 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; + int 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 = octeon_alloc_soft_command(oct, 0, 16, 0); + if (!sc) + return -ENOMEM; sc->iq_no = lio->linfo.txpciq[0].s.q_no; @@ -2976,23 +3030,21 @@ OPCODE_NIC_SET_TRUSTED_VF, 0, vfidx + 1, trusted); - sc->callback = trusted_vf_callback; - sc->callback_arg = sc; - sc->wait_time = 1000; + init_completion(&sc->complete); + sc->sc_status = OCTEON_REQUEST_PENDING; retval = octeon_send_soft_command(oct, sc); if (retval == IQ_SEND_FAILED) { + octeon_free_soft_command(oct, sc); 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; - } + retval = wait_for_sc_completion_timeout(oct, sc, 0); + if (retval) + return (retval); - octeon_free_soft_command(oct, sc); + WRITE_ONCE(sc->caller_is_done, true); + } return retval; } @@ -3055,6 +3107,7 @@ struct lio *lio = GET_LIO(netdev); struct octeon_device *oct = lio->oct_dev; struct octnic_ctrl_pkt nctrl; + int ret = 0; if (vfidx < 0 || vfidx >= oct->sriov_info.num_vfs_alloced) return -EINVAL; @@ -3070,13 +3123,15 @@ nctrl.ncmd.s.more = 0; nctrl.iq_no = lio->linfo.txpciq[0].s.q_no; nctrl.cb_fn = NULL; - nctrl.wait_time = LIO_CMD_WAIT_TM; - octnet_send_nic_ctrl_pkt(oct, &nctrl); + ret = octnet_send_nic_ctrl_pkt(oct, &nctrl); - oct->sriov_info.vf_linkstate[vfidx] = linkstate; + if (!ret) + oct->sriov_info.vf_linkstate[vfidx] = linkstate; + else if (ret > 0) + ret = -EIO; - return 0; + return ret; } static int @@ -3094,7 +3149,8 @@ } static int -liquidio_eswitch_mode_set(struct devlink *devlink, u16 mode) +liquidio_eswitch_mode_set(struct devlink *devlink, u16 mode, + struct netlink_ext_ack *extack) { struct lio_devlink_priv *priv; struct octeon_device *oct; @@ -3133,7 +3189,8 @@ }; static int -lio_pf_switchdev_attr_get(struct net_device *dev, struct switchdev_attr *attr) +liquidio_get_port_parent_id(struct net_device *dev, + struct netdev_phys_item_id *ppid) { struct lio *lio = GET_LIO(dev); struct octeon_device *oct = lio->oct_dev; @@ -3141,23 +3198,11 @@ if (oct->eswitch_mode != DEVLINK_ESWITCH_MODE_SWITCHDEV) return -EOPNOTSUPP; - switch (attr->id) { - case SWITCHDEV_ATTR_ID_PORT_PARENT_ID: - attr->u.ppid.id_len = ETH_ALEN; - ether_addr_copy(attr->u.ppid.id, - (void *)&lio->linfo.hw_addr + 2); - break; - - default: - return -EOPNOTSUPP; - } + ppid->id_len = ETH_ALEN; + ether_addr_copy(ppid->id, (void *)&lio->linfo.hw_addr + 2); return 0; } - -static const struct switchdev_ops lio_pf_switchdev_ops = { - .switchdev_port_attr_get = lio_pf_switchdev_attr_get, -}; static int liquidio_get_vf_stats(struct net_device *netdev, int vfidx, struct ifla_vf_stats *vf_stats) @@ -3199,17 +3244,20 @@ .ndo_do_ioctl = liquidio_ioctl, .ndo_fix_features = liquidio_fix_features, .ndo_set_features = liquidio_set_features, - .ndo_udp_tunnel_add = liquidio_add_vxlan_port, - .ndo_udp_tunnel_del = liquidio_del_vxlan_port, + .ndo_udp_tunnel_add = udp_tunnel_nic_add_port, + .ndo_udp_tunnel_del = udp_tunnel_nic_del_port, .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_spoofchk = liquidio_set_vf_spoofchk, .ndo_set_vf_trust = liquidio_set_vf_trust, .ndo_set_vf_link_state = liquidio_set_vf_link_state, .ndo_get_vf_stats = liquidio_get_vf_stats, + .ndo_get_port_parent_id = liquidio_get_port_parent_id, }; -/** \brief Entry point for the liquidio module +/** + * liquidio_init - Entry point for the liquidio module */ static int __init liquidio_init(void) { @@ -3292,8 +3340,8 @@ } /** - * \brief Setup network interfaces - * @param octeon_dev octeon device + * setup_nic_devices - Setup network interfaces + * @octeon_dev: octeon device * * Called during init time for each device. It assumes the NIC * is already up and running. The link information for each @@ -3307,7 +3355,6 @@ unsigned long micro; u32 cur_ver; struct octeon_soft_command *sc; - struct liquidio_if_cfg_context *ctx; struct liquidio_if_cfg_resp *resp; struct octdev_props *props; int retval, num_iqueues, num_oqueues; @@ -3315,7 +3362,7 @@ union oct_nic_if_cfg if_cfg; unsigned int base_queue; unsigned int gmx_port_id; - u32 resp_size, ctx_size, data_size; + u32 resp_size, data_size; u32 ifidx_or_pfnum; struct lio_version *vdata; struct devlink *devlink; @@ -3340,13 +3387,11 @@ for (i = 0; i < octeon_dev->ifcount; i++) { resp_size = sizeof(struct liquidio_if_cfg_resp); - ctx_size = sizeof(struct liquidio_if_cfg_context); data_size = sizeof(struct lio_version); sc = (struct octeon_soft_command *) octeon_alloc_soft_command(octeon_dev, data_size, - resp_size, ctx_size); + resp_size, 0); resp = (struct liquidio_if_cfg_resp *)sc->virtrptr; - ctx = (struct liquidio_if_cfg_context *)sc->ctxptr; vdata = (struct lio_version *)sc->virtdptr; *((u64 *)vdata) = 0; @@ -3376,9 +3421,6 @@ dev_dbg(&octeon_dev->pci_dev->dev, "requesting config for interface %d, iqs %d, oqs %d\n", ifidx_or_pfnum, num_iqueues, num_oqueues); - WRITE_ONCE(ctx->cond, 0); - ctx->octeon_id = lio_get_device_id(octeon_dev); - init_waitqueue_head(&ctx->wc); if_cfg.u64 = 0; if_cfg.s.num_iqueues = num_iqueues; @@ -3392,9 +3434,8 @@ OPCODE_NIC_IF_CFG, 0, if_cfg.u64, 0); - sc->callback = lio_if_cfg_callback; - sc->callback_arg = sc; - sc->wait_time = LIO_IFCFG_WAIT_TIME; + init_completion(&sc->complete); + sc->sc_status = OCTEON_REQUEST_PENDING; retval = octeon_send_soft_command(octeon_dev, sc); if (retval == IQ_SEND_FAILED) { @@ -3402,22 +3443,26 @@ "iq/oq config failed status: %x\n", retval); /* Soft instr is freed by driver in case of failure. */ - goto setup_nic_dev_fail; + octeon_free_soft_command(octeon_dev, sc); + return(-EIO); } /* 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) { - dev_err(&octeon_dev->pci_dev->dev, "Wait interrupted\n"); - goto setup_nic_wait_intr; - } + retval = wait_for_sc_completion_timeout(octeon_dev, sc, 0); + if (retval) + return retval; retval = resp->status; if (retval) { dev_err(&octeon_dev->pci_dev->dev, "iq/oq config failed\n"); - goto setup_nic_dev_fail; + WRITE_ONCE(sc->caller_is_done, true); + goto setup_nic_dev_done; } + snprintf(octeon_dev->fw_info.liquidio_firmware_version, + 32, "%s", + resp->cfg_info.liquidio_firmware_version); /* Verify f/w version (in case of 'auto' loading from flash) */ fw_ver = octeon_dev->fw_info.liquidio_firmware_version; @@ -3427,7 +3472,8 @@ dev_err(&octeon_dev->pci_dev->dev, "Unmatched firmware version. Expected %s.x, got %s.\n", LIQUIDIO_BASE_VERSION, fw_ver); - goto setup_nic_dev_fail; + WRITE_ONCE(sc->caller_is_done, true); + goto setup_nic_dev_done; } else if (atomic_read(octeon_dev->adapter_fw_state) == FW_IS_PRELOADED) { dev_info(&octeon_dev->pci_dev->dev, @@ -3454,7 +3500,8 @@ "Got bad iqueues (%016llx) or oqueues (%016llx) from firmware.\n", resp->cfg_info.iqmask, resp->cfg_info.oqmask); - goto setup_nic_dev_fail; + WRITE_ONCE(sc->caller_is_done, true); + goto setup_nic_dev_done; } if (OCTEON_CN6XXX(octeon_dev)) { @@ -3473,7 +3520,8 @@ if (!netdev) { dev_err(&octeon_dev->pci_dev->dev, "Device allocation failed\n"); - goto setup_nic_dev_fail; + WRITE_ONCE(sc->caller_is_done, true); + goto setup_nic_dev_done; } SET_NETDEV_DEV(netdev, &octeon_dev->pci_dev->dev); @@ -3482,20 +3530,21 @@ * netdev tasks. */ netdev->netdev_ops = &lionetdevops; - SWITCHDEV_SET_OPS(netdev, &lio_pf_switchdev_ops); retval = netif_set_real_num_rx_queues(netdev, num_oqueues); if (retval) { dev_err(&octeon_dev->pci_dev->dev, "setting real number rx failed\n"); - goto setup_nic_dev_fail; + WRITE_ONCE(sc->caller_is_done, true); + goto setup_nic_dev_free; } retval = netif_set_real_num_tx_queues(netdev, num_iqueues); if (retval) { dev_err(&octeon_dev->pci_dev->dev, "setting real number tx failed\n"); - goto setup_nic_dev_fail; + WRITE_ONCE(sc->caller_is_done, true); + goto setup_nic_dev_free; } lio = GET_LIO(netdev); @@ -3521,6 +3570,8 @@ lio->linfo.hw_addr = resp->cfg_info.linfo.hw_addr; lio->linfo.gmxport = resp->cfg_info.linfo.gmxport; lio->linfo.link.u64 = resp->cfg_info.linfo.link.u64; + + WRITE_ONCE(sc->caller_is_done, true); lio->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); @@ -3549,6 +3600,8 @@ netdev->hw_enc_features = (lio->enc_dev_capability & ~NETIF_F_LRO); + + netdev->udp_tunnel_nic_info = &liquidio_udp_tunnels; lio->dev_capability |= NETIF_F_GSO_UDP_TUNNEL; @@ -3588,7 +3641,7 @@ dev_err(&octeon_dev->pci_dev->dev, "Error setting VF%d MAC address\n", j); - goto setup_nic_dev_fail; + goto setup_nic_dev_free; } } @@ -3610,7 +3663,7 @@ lio->linfo.num_txpciq, lio->linfo.num_rxpciq)) { dev_err(&octeon_dev->pci_dev->dev, "I/O queues creation failed\n"); - goto setup_nic_dev_fail; + goto setup_nic_dev_free; } ifstate_set(lio, LIO_IFSTATE_DROQ_OPS); @@ -3621,7 +3674,7 @@ if (lio_setup_glists(octeon_dev, lio, num_iqueues)) { dev_err(&octeon_dev->pci_dev->dev, "Gather list allocation failed\n"); - goto setup_nic_dev_fail; + goto setup_nic_dev_free; } /* Register ethtool support */ @@ -3643,20 +3696,20 @@ OCTNET_CMD_VERBOSE_ENABLE, 0); if (setup_link_status_change_wq(netdev)) - goto setup_nic_dev_fail; + goto setup_nic_dev_free; if ((octeon_dev->fw_info.app_cap_flags & LIQUIDIO_TIME_SYNC_CAP) && setup_sync_octeon_time_wq(netdev)) - goto setup_nic_dev_fail; + goto setup_nic_dev_free; if (setup_rx_oom_poll_fn(netdev)) - goto setup_nic_dev_fail; + goto setup_nic_dev_free; /* Register the network device with the OS */ if (register_netdev(netdev)) { dev_err(&octeon_dev->pci_dev->dev, "Device registration failed\n"); - goto setup_nic_dev_fail; + goto setup_nic_dev_free; } dev_dbg(&octeon_dev->pci_dev->dev, @@ -3678,8 +3731,6 @@ dev_dbg(&octeon_dev->pci_dev->dev, "NIC ifidx:%d Setup successful\n", i); - - octeon_free_soft_command(octeon_dev, sc); if (octeon_dev->subsystem_id == OCTEON_CN2350_25GB_SUBSYS_ID || @@ -3709,13 +3760,20 @@ } octeon_dev->speed_boot = octeon_dev->speed_setting; + /* don't read FEC setting if unsupported by f/w (see above) */ + if (octeon_dev->speed_boot == 25 && + !octeon_dev->no_speed_setting) { + liquidio_get_fec(lio); + octeon_dev->props[lio->ifidx].fec_boot = + octeon_dev->props[lio->ifidx].fec; + } } devlink = devlink_alloc(&liquidio_devlink_ops, sizeof(struct lio_devlink_priv)); if (!devlink) { dev_err(&octeon_dev->pci_dev->dev, "devlink alloc failed\n"); - goto setup_nic_wait_intr; + goto setup_nic_dev_free; } lio_devlink = devlink_priv(devlink); @@ -3725,7 +3783,7 @@ devlink_free(devlink); dev_err(&octeon_dev->pci_dev->dev, "devlink registration failed\n"); - goto setup_nic_wait_intr; + goto setup_nic_dev_free; } octeon_dev->devlink = devlink; @@ -3733,17 +3791,16 @@ return 0; -setup_nic_dev_fail: - - octeon_free_soft_command(octeon_dev, sc); - -setup_nic_wait_intr: +setup_nic_dev_free: while (i--) { dev_err(&octeon_dev->pci_dev->dev, "NIC ifidx:%d Setup failed\n", i); liquidio_destroy_nic_device(octeon_dev, i); } + +setup_nic_dev_done: + return -ENODEV; } @@ -3848,8 +3905,8 @@ #endif /** - * \brief initialize the NIC - * @param oct octeon device + * liquidio_init_nic_module - initialize the NIC + * @oct: octeon device * * This initialization routine is called once the Octeon device application is * up and running @@ -3904,9 +3961,10 @@ } /** - * \brief starter callback that invokes the remaining initialization work after - * the NIC is up and running. - * @param octptr work struct work_struct + * nic_starter - finish init + * @work: work struct work_struct + * + * starter callback that invokes the remaining initialization work after the NIC is up and running. */ static void nic_starter(struct work_struct *work) { @@ -3999,8 +4057,8 @@ } /** - * \brief Device initialization for each Octeon device that is probed - * @param octeon_dev octeon device + * octeon_device_init - Device initialization for each Octeon device that is probed + * @octeon_dev: octeon device */ static int octeon_device_init(struct octeon_device *octeon_dev) { @@ -4169,8 +4227,7 @@ /* Initialize the tasklet that handles output queue packet processing.*/ dev_dbg(&octeon_dev->pci_dev->dev, "Initializing droq tasklet\n"); - tasklet_init(&oct_priv->droq_tasklet, octeon_droq_bh, - (unsigned long)octeon_dev); + tasklet_setup(&oct_priv->droq_tasklet, octeon_droq_bh); /* Setup the interrupt handler and record the INT SUM register address */ @@ -4274,16 +4331,17 @@ complete(&handshake[octeon_dev->octeon_id].init); atomic_set(&octeon_dev->status, OCT_DEV_HOST_OK); + oct_priv->dev = octeon_dev; return 0; } /** - * \brief Debug console print function - * @param octeon_dev octeon device - * @param console_num console number - * @param prefix first portion of line to display - * @param suffix second portion of line to display + * octeon_dbg_console_print - Debug console print function + * @oct: octeon device + * @console_num: console number + * @prefix: first portion of line to display + * @suffix: second portion of line to display * * The OCTEON debug console outputs entire lines (excluding '\n'). * Normally, the line will be passed in the 'prefix' parameter. @@ -4306,7 +4364,7 @@ } /** - * \brief Exits the module + * liquidio_exit - Exits the module */ static void __exit liquidio_exit(void) { -- Gitblit v1.6.2