/********************************************************************** * Author: Cavium, Inc. * * Contact: [email protected] * Please include "LiquidIO" in the subject. * * Copyright (c) 2003-2016 Cavium, Inc. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as * published by the Free Software Foundation. * * This file is distributed in the hope that it will be useful, but * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or * NONINFRINGEMENT. See the GNU General Public License for more details. ***********************************************************************/ #include <linux/module.h> #include <linux/interrupt.h> #include <linux/pci.h> #include <linux/firmware.h> #include <net/vxlan.h> #include <linux/kthread.h> #include "liquidio_common.h" #include "octeon_droq.h" #include "octeon_iq.h" #include "response_manager.h" #include "octeon_device.h" #include "octeon_nic.h" #include "octeon_main.h" #include "octeon_network.h" #include "cn66xx_regs.h" #include "cn66xx_device.h" #include "cn68xx_device.h" #include "cn23xx_pf_device.h" #include "liquidio_image.h" #include "lio_vf_rep.h" MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …; MODULE_FIRMWARE(…) …; MODULE_FIRMWARE(…) …; MODULE_FIRMWARE(…) …; MODULE_FIRMWARE(…) …; static int ddr_timeout = …; module_param(ddr_timeout, int, 0644); MODULE_PARM_DESC(…) …; #define DEFAULT_MSG_ENABLE … static int debug = …; module_param(debug, int, 0644); MODULE_PARM_DESC(…) …; static char fw_type[LIO_MAX_FW_TYPE_LEN] = …; module_param_string(…); MODULE_PARM_DESC(…) …; static u32 console_bitmask; module_param(console_bitmask, int, 0644); MODULE_PARM_DESC(…) …; /** * 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) { … } /* Polling interval for determining when NIC application is alive */ #define LIQUIDIO_STARTER_POLL_INTERVAL_MS … /* runtime link query interval */ #define LIQUIDIO_LINK_QUERY_INTERVAL_MS … /* update localtime to octeon firmware every 60 seconds. * make firmware to use same time reference, so that it will be easy to * correlate firmware logged events/errors with host events, for debugging. */ #define LIO_SYNC_OCTEON_TIME_INTERVAL_MS … /* time to wait for possible in-flight requests in milliseconds */ #define WAIT_INFLIGHT_REQUEST … struct oct_timestamp_resp { … }; #define OCT_TIMESTAMP_RESP_SIZE … tx_info; /* 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. */ #define OCTNIC_GSO_MAX_HEADER_SIZE … #define OCTNIC_GSO_MAX_SIZE … struct handshake { … }; #ifdef CONFIG_PCI_IOV static int liquidio_enable_sriov(struct pci_dev *dev, int num_vfs); #endif static int octeon_dbg_console_print(struct octeon_device *oct, u32 console_num, char *prefix, char *suffix); static int octeon_device_init(struct octeon_device *); static int liquidio_stop(struct net_device *netdev); static void liquidio_remove(struct pci_dev *pdev); static int liquidio_probe(struct pci_dev *pdev, const struct pci_device_id *ent); static int liquidio_set_vf_link_state(struct net_device *netdev, int vfidx, int linkstate); static struct handshake handshake[MAX_OCTEON_DEVICES]; static struct completion first_stage; static void octeon_droq_bh(struct tasklet_struct *t) { … } static int lio_wait_for_oq_pkts(struct octeon_device *oct) { … } /** * 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) { … } /** * 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) { … } /** * 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) { … } /** * 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) { … } /** * 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. */ static pci_ers_result_t liquidio_pcie_error_detected(struct pci_dev *pdev, pci_channel_state_t state) { … } /** * liquidio_pcie_mmio_enabled - mmio handler * @pdev: Pointer to PCI device */ static pci_ers_result_t liquidio_pcie_mmio_enabled(struct pci_dev __maybe_unused *pdev) { … } /** * 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 __maybe_unused *pdev) { … } /** * 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 __maybe_unused *pdev) { … } #define liquidio_suspend … #define liquidio_resume … /* For PCI-E Advanced Error Recovery (AER) Interface */ static const struct pci_error_handlers liquidio_err_handler = …; static const struct pci_device_id liquidio_pci_tbl[] = …; 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 = …; /** * liquidio_init_pci - register PCI driver */ static int liquidio_init_pci(void) { … } /** * liquidio_deinit_pci - unregister PCI driver */ static void liquidio_deinit_pci(void) { … } /** * 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) { … } /** * print_link_info - Print link information * @netdev: network device */ static void print_link_info(struct net_device *netdev) { … } /** * octnet_link_status_change - Routine to notify MTU change * @work: work_struct data structure */ static void octnet_link_status_change(struct work_struct *work) { … } /** * 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) { … } static inline void cleanup_link_status_change_wq(struct net_device *netdev) { … } /** * 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. */ static inline void update_link_status(struct net_device *netdev, union oct_link_status *ls) { … } /** * 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 * * @work: work scheduled to send time update to octeon firmware **/ static void lio_sync_octeon_time(struct work_struct *work) { … } /** * 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 **/ static inline int setup_sync_octeon_time_wq(struct net_device *netdev) { … } /** * cleanup_sync_octeon_time_wq - destroy wq * * @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) { … } static struct octeon_device *get_other_octeon_device(struct octeon_device *oct) { … } static void disable_all_vf_links(struct octeon_device *oct) { … } static int liquidio_watchdog(void *param) { … } /** * liquidio_probe - PCI probe handler * @pdev: PCI device structure * @ent: unused */ static int liquidio_probe(struct pci_dev *pdev, const struct pci_device_id __maybe_unused *ent) { … } static bool fw_type_is_auto(void) { … } /** * octeon_pci_flr - PCI FLR for each Octeon device. * @oct: octeon device */ static void octeon_pci_flr(struct octeon_device *oct) { … } /** * octeon_destroy_resources - Destroy resources associated with octeon device * @oct: octeon device */ static void octeon_destroy_resources(struct octeon_device *oct) { … } /** * send_rx_ctrl_cmd - Send Rx control command * @lio: per-network private data * @start_stop: whether to start or stop */ static int send_rx_ctrl_cmd(struct lio *lio, int start_stop) { … } /** * 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. */ static void liquidio_destroy_nic_device(struct octeon_device *oct, int ifidx) { … } /** * liquidio_stop_nic_module - Stop complete NIC functionality * @oct: octeon device */ static int liquidio_stop_nic_module(struct octeon_device *oct) { … } /** * liquidio_remove - Cleans up resources at unload time * @pdev: PCI device structure */ static void liquidio_remove(struct pci_dev *pdev) { … } /** * 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) { … } /** * octeon_pci_os_setup - PCI initialization for each Octeon device. * @oct: octeon device */ static int octeon_pci_os_setup(struct octeon_device *oct) { … } /** * free_netbuf - Unmap and free network buffer * @buf: buffer */ static void free_netbuf(void *buf) { … } /** * free_netsgbuf - Unmap and free gather buffer * @buf: buffer */ static void free_netsgbuf(void *buf) { … } /** * free_netsgbuf_with_resp - Unmap and free gather buffer with response * @buf: buffer */ static void free_netsgbuf_with_resp(void *buf) { … } /** * liquidio_ptp_adjfine - Adjust ptp frequency * @ptp: PTP clock info * @scaled_ppm: how much to adjust by, in scaled parts-per-million * * Scaled parts per million is ppm with a 16-bit binary fractional field. */ static int liquidio_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) { … } /** * 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) { … } /** * 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) { … } /** * 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) { … } /** * 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 __maybe_unused *ptp, struct ptp_clock_request __maybe_unused *rq, int __maybe_unused on) { … } /** * oct_ptp_open - Open PTP clock source * @netdev: network device */ static void oct_ptp_open(struct net_device *netdev) { … } /** * liquidio_ptp_init - Init PTP clock * @oct: octeon device */ static void liquidio_ptp_init(struct octeon_device *oct) { … } /** * load_firmware - Load firmware to device * @oct: octeon device * * Maps device to firmware filename, requests firmware, and downloads it */ static int load_firmware(struct octeon_device *oct) { … } /** * 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) { … } /** * setup_tx_poll_fn - Sets up the txq poll check * @netdev: network device */ static inline int setup_tx_poll_fn(struct net_device *netdev) { … } static inline void cleanup_tx_poll_fn(struct net_device *netdev) { … } /** * liquidio_open - Net device open for LiquidIO * @netdev: network device */ static int liquidio_open(struct net_device *netdev) { … } /** * liquidio_stop - Net device stop for LiquidIO * @netdev: network device */ static int liquidio_stop(struct net_device *netdev) { … } /** * 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. */ static inline enum octnet_ifflags get_new_flags(struct net_device *netdev) { … } /** * liquidio_set_mcast_list - Net device set_multicast_list * @netdev: network device */ static void liquidio_set_mcast_list(struct net_device *netdev) { … } /** * 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) { … } static void liquidio_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *lstats) { … } /** * hwtstamp_ioctl - Handler for SIOCSHWTSTAMP ioctl * @netdev: network device * @ifr: interface request */ static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr) { … } /** * 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) { … } /** * 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, void *buf) { … } /** * 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, struct octnet_buf_free_info *finfo, int xmit_more) { … } /** * 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) { … } /** * 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, unsigned int txqueue) { … } static int liquidio_vlan_rx_add_vid(struct net_device *netdev, __be16 proto __attribute__((unused)), u16 vid) { … } static int liquidio_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto __attribute__((unused)), u16 vid) { … } /** * 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) { … } /** * 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 * Return: SUCCESS or FAILURE */ static int liquidio_vxlan_port_command(struct net_device *netdev, int command, u16 vxlan_port, u8 vxlan_cmd_bit) { … } static int liquidio_udp_tunnel_set_port(struct net_device *netdev, unsigned int table, unsigned int entry, struct udp_tunnel_info *ti) { … } static int liquidio_udp_tunnel_unset_port(struct net_device *netdev, unsigned int table, unsigned int entry, struct udp_tunnel_info *ti) { … } static const struct udp_tunnel_nic_info liquidio_udp_tunnels = …; /** * 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) { … } /** * 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) { … } static int __liquidio_set_vf_mac(struct net_device *netdev, int vfidx, u8 *mac, bool is_admin_assigned) { … } static int liquidio_set_vf_mac(struct net_device *netdev, int vfidx, u8 *mac) { … } static int liquidio_set_vf_spoofchk(struct net_device *netdev, int vfidx, bool enable) { … } static int liquidio_set_vf_vlan(struct net_device *netdev, int vfidx, u16 vlan, u8 qos, __be16 vlan_proto) { … } static int liquidio_get_vf_config(struct net_device *netdev, int vfidx, struct ifla_vf_info *ivi) { … } static int liquidio_send_vf_trust_cmd(struct lio *lio, int vfidx, bool trusted) { … } static int liquidio_set_vf_trust(struct net_device *netdev, int vfidx, bool setting) { … } static int liquidio_set_vf_link_state(struct net_device *netdev, int vfidx, int linkstate) { … } static int liquidio_eswitch_mode_get(struct devlink *devlink, u16 *mode) { … } static int liquidio_eswitch_mode_set(struct devlink *devlink, u16 mode, struct netlink_ext_ack *extack) { … } static const struct devlink_ops liquidio_devlink_ops = …; static int liquidio_get_port_parent_id(struct net_device *dev, struct netdev_phys_item_id *ppid) { … } static int liquidio_get_vf_stats(struct net_device *netdev, int vfidx, struct ifla_vf_stats *vf_stats) { … } static const struct net_device_ops lionetdevops = …; /** * liquidio_init - Entry point for the liquidio module */ static int __init liquidio_init(void) { … } static int lio_nic_info(struct octeon_recv_info *recv_info, void *buf) { … } /** * 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 * interface is passed in link_info. */ static int setup_nic_devices(struct octeon_device *octeon_dev) { … } #ifdef CONFIG_PCI_IOV static int octeon_enable_sriov(struct octeon_device *oct) { … } static int lio_pci_sriov_disable(struct octeon_device *oct) { … } static int liquidio_enable_sriov(struct pci_dev *dev, int num_vfs) { … } #endif /** * liquidio_init_nic_module - initialize the NIC * @oct: octeon device * * This initialization routine is called once the Octeon device application is * up and running */ static int liquidio_init_nic_module(struct octeon_device *oct) { … } /** * 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) { … } static int octeon_recv_vf_drv_notice(struct octeon_recv_info *recv_info, void *buf) { … } /** * 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) { … } /** * 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. * However, due to buffering, it is possible for a line to be split into two * parts, in which case they will be passed as the 'prefix' parameter and * 'suffix' parameter. */ static int octeon_dbg_console_print(struct octeon_device *oct, u32 console_num, char *prefix, char *suffix) { … } /** * liquidio_exit - Exits the module */ static void __exit liquidio_exit(void) { … } module_init(…) …; module_exit(liquidio_exit);