Merge branch 'ionic-updates'

Shannon Nelson says:

====================
ionic updates

These are a few of the driver updates we've been working on internally.
These clean up a few mismatched struct comments, add checking for dead
firmware, fix an initialization bug, and change the Rx buffer management.

These are based on net-next v5.4-rc3-709-g985fd98ab5cc.

v2: clear napi->skb in the error case in ionic_rx_frags()
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2019-10-25 20:52:36 -07:00
commit 0629d2456a
7 changed files with 413 additions and 186 deletions

View File

@ -12,7 +12,7 @@ struct ionic_lif;
#define IONIC_DRV_NAME "ionic"
#define IONIC_DRV_DESCRIPTION "Pensando Ethernet NIC Driver"
#define IONIC_DRV_VERSION "0.15.0-k"
#define IONIC_DRV_VERSION "0.18.0-k"
#define PCI_VENDOR_ID_PENSANDO 0x1dd8
@ -46,6 +46,8 @@ struct ionic {
DECLARE_BITMAP(intrs, IONIC_INTR_CTRL_REGS_MAX);
struct work_struct nb_work;
struct notifier_block nb;
struct timer_list watchdog_timer;
int watchdog_period;
};
struct ionic_admin_ctx {

View File

@ -11,6 +11,16 @@
#include "ionic_dev.h"
#include "ionic_lif.h"
static void ionic_watchdog_cb(struct timer_list *t)
{
struct ionic *ionic = from_timer(ionic, t, watchdog_timer);
mod_timer(&ionic->watchdog_timer,
round_jiffies(jiffies + ionic->watchdog_period));
ionic_heartbeat_check(ionic);
}
void ionic_init_devinfo(struct ionic *ionic)
{
struct ionic_dev *idev = &ionic->idev;
@ -72,6 +82,11 @@ int ionic_dev_setup(struct ionic *ionic)
return -EFAULT;
}
timer_setup(&ionic->watchdog_timer, ionic_watchdog_cb, 0);
ionic->watchdog_period = IONIC_WATCHDOG_SECS * HZ;
mod_timer(&ionic->watchdog_timer,
round_jiffies(jiffies + ionic->watchdog_period));
idev->db_pages = bar->vaddr;
idev->phy_db_pages = bar->bus_addr;
@ -80,10 +95,53 @@ int ionic_dev_setup(struct ionic *ionic)
void ionic_dev_teardown(struct ionic *ionic)
{
/* place holder */
del_timer_sync(&ionic->watchdog_timer);
}
/* Devcmd Interface */
int ionic_heartbeat_check(struct ionic *ionic)
{
struct ionic_dev *idev = &ionic->idev;
unsigned long hb_time;
u32 fw_status;
u32 hb;
/* wait a little more than one second before testing again */
hb_time = jiffies;
if (time_before(hb_time, (idev->last_hb_time + ionic->watchdog_period)))
return 0;
/* firmware is useful only if fw_status is non-zero */
fw_status = ioread32(&idev->dev_info_regs->fw_status);
if (!fw_status)
return -ENXIO;
/* early FW has no heartbeat, else FW will return non-zero */
hb = ioread32(&idev->dev_info_regs->fw_heartbeat);
if (!hb)
return 0;
/* are we stalled? */
if (hb == idev->last_hb) {
/* only complain once for each stall seen */
if (idev->last_hb_time != 1) {
dev_info(ionic->dev, "FW heartbeat stalled at %d\n",
idev->last_hb);
idev->last_hb_time = 1;
}
return -ENXIO;
}
if (idev->last_hb_time == 1)
dev_info(ionic->dev, "FW heartbeat restored at %d\n", hb);
idev->last_hb = hb;
idev->last_hb_time = hb_time;
return 0;
}
u8 ionic_dev_cmd_status(struct ionic_dev *idev)
{
return ioread8(&idev->dev_cmd_regs->comp.comp.status);

View File

@ -16,6 +16,7 @@
#define IONIC_MIN_TXRX_DESC 16
#define IONIC_DEF_TXRX_DESC 4096
#define IONIC_LIFS_MAX 1024
#define IONIC_WATCHDOG_SECS 5
#define IONIC_ITR_COAL_USEC_DEFAULT 64
#define IONIC_DEV_CMD_REG_VERSION 1
@ -123,6 +124,9 @@ struct ionic_dev {
union ionic_dev_info_regs __iomem *dev_info_regs;
union ionic_dev_cmd_regs __iomem *dev_cmd_regs;
unsigned long last_hb_time;
u32 last_hb;
u64 __iomem *db_pages;
dma_addr_t phy_db_pages;
@ -151,12 +155,19 @@ typedef void (*ionic_desc_cb)(struct ionic_queue *q,
struct ionic_desc_info *desc_info,
struct ionic_cq_info *cq_info, void *cb_arg);
struct ionic_page_info {
struct page *page;
dma_addr_t dma_addr;
};
struct ionic_desc_info {
void *desc;
void *sg_desc;
struct ionic_desc_info *next;
unsigned int index;
unsigned int left;
unsigned int npages;
struct ionic_page_info pages[IONIC_RX_MAX_SG_ELEMS + 1];
ionic_desc_cb cb;
void *cb_arg;
};
@ -295,5 +306,6 @@ void ionic_q_post(struct ionic_queue *q, bool ring_doorbell, ionic_desc_cb cb,
void ionic_q_rewind(struct ionic_queue *q, struct ionic_desc_info *start);
void ionic_q_service(struct ionic_queue *q, struct ionic_cq_info *cq_info,
unsigned int stop_index);
int ionic_heartbeat_check(struct ionic *ionic);
#endif /* _IONIC_DEV_H_ */

View File

@ -111,7 +111,7 @@ struct ionic_admin_cmd {
};
/**
* struct admin_comp - General admin command completion format
* struct ionic_admin_comp - General admin command completion format
* @status: The status of the command (enum status_code)
* @comp_index: The index in the descriptor ring for which this
* is the completion.
@ -134,7 +134,7 @@ static inline u8 color_match(u8 color, u8 done_color)
}
/**
* struct nop_cmd - NOP command
* struct ionic_nop_cmd - NOP command
* @opcode: opcode
*/
struct ionic_nop_cmd {
@ -143,7 +143,7 @@ struct ionic_nop_cmd {
};
/**
* struct nop_comp - NOP command completion
* struct ionic_nop_comp - NOP command completion
* @status: The status of the command (enum status_code)
*/
struct ionic_nop_comp {
@ -152,7 +152,7 @@ struct ionic_nop_comp {
};
/**
* struct dev_init_cmd - Device init command
* struct ionic_dev_init_cmd - Device init command
* @opcode: opcode
* @type: device type
*/
@ -172,7 +172,7 @@ struct ionic_dev_init_comp {
};
/**
* struct dev_reset_cmd - Device reset command
* struct ionic_dev_reset_cmd - Device reset command
* @opcode: opcode
*/
struct ionic_dev_reset_cmd {
@ -192,7 +192,7 @@ struct ionic_dev_reset_comp {
#define IONIC_IDENTITY_VERSION_1 1
/**
* struct dev_identify_cmd - Driver/device identify command
* struct ionic_dev_identify_cmd - Driver/device identify command
* @opcode: opcode
* @ver: Highest version of identify supported by driver
*/
@ -284,7 +284,7 @@ enum ionic_lif_type {
};
/**
* struct lif_identify_cmd - lif identify command
* struct ionic_lif_identify_cmd - lif identify command
* @opcode: opcode
* @type: lif type (enum lif_type)
* @ver: version of identify returned by device
@ -297,7 +297,7 @@ struct ionic_lif_identify_cmd {
};
/**
* struct lif_identify_comp - lif identify command completion
* struct ionic_lif_identify_comp - lif identify command completion
* @status: status of the command (enum status_code)
* @ver: version of identify returned by device
*/
@ -325,7 +325,7 @@ enum ionic_logical_qtype {
};
/**
* struct lif_logical_qtype - Descriptor of logical to hardware queue type.
* struct ionic_lif_logical_qtype - Descriptor of logical to hardware queue type.
* @qtype: Hardware Queue Type.
* @qid_count: Number of Queue IDs of the logical type.
* @qid_base: Minimum Queue ID of the logical type.
@ -349,7 +349,7 @@ enum ionic_lif_state {
* @name: lif name
* @mtu: mtu
* @mac: station mac address
* @features: features (enum eth_hw_features)
* @features: features (enum ionic_eth_hw_features)
* @queue_count: queue counts per queue-type
*/
union ionic_lif_config {
@ -367,7 +367,7 @@ union ionic_lif_config {
};
/**
* struct lif_identity - lif identity information (type-specific)
* struct ionic_lif_identity - lif identity information (type-specific)
*
* @capabilities LIF capabilities
*
@ -441,11 +441,11 @@ union ionic_lif_identity {
};
/**
* struct lif_init_cmd - LIF init command
* struct ionic_lif_init_cmd - LIF init command
* @opcode: opcode
* @type: LIF type (enum lif_type)
* @index: LIF index
* @info_pa: destination address for lif info (struct lif_info)
* @info_pa: destination address for lif info (struct ionic_lif_info)
*/
struct ionic_lif_init_cmd {
u8 opcode;
@ -457,7 +457,7 @@ struct ionic_lif_init_cmd {
};
/**
* struct lif_init_comp - LIF init command completion
* struct ionic_lif_init_comp - LIF init command completion
* @status: The status of the command (enum status_code)
*/
struct ionic_lif_init_comp {
@ -468,7 +468,7 @@ struct ionic_lif_init_comp {
};
/**
* struct q_init_cmd - Queue init command
* struct ionic_q_init_cmd - Queue init command
* @opcode: opcode
* @type: Logical queue type
* @ver: Queue version (defines opcode/descriptor scope)
@ -525,7 +525,7 @@ struct ionic_q_init_cmd {
};
/**
* struct q_init_comp - Queue init command completion
* struct ionic_q_init_comp - Queue init command completion
* @status: The status of the command (enum status_code)
* @ver: Queue version (defines opcode/descriptor scope)
* @comp_index: The index in the descriptor ring for which this
@ -556,7 +556,7 @@ enum ionic_txq_desc_opcode {
};
/**
* struct txq_desc - Ethernet Tx queue descriptor format
* struct ionic_txq_desc - Ethernet Tx queue descriptor format
* @opcode: Tx operation, see TXQ_DESC_OPCODE_*:
*
* IONIC_TXQ_DESC_OPCODE_CSUM_NONE:
@ -735,7 +735,7 @@ static inline void decode_txq_desc_cmd(u64 cmd, u8 *opcode, u8 *flags,
#define IONIC_RX_MAX_SG_ELEMS 8
/**
* struct txq_sg_desc - Transmit scatter-gather (SG) list
* struct ionic_txq_sg_desc - Transmit scatter-gather (SG) list
* @addr: DMA address of SG element data buffer
* @len: Length of SG element data buffer, in bytes
*/
@ -748,7 +748,7 @@ struct ionic_txq_sg_desc {
};
/**
* struct txq_comp - Ethernet transmit queue completion descriptor
* struct ionic_txq_comp - Ethernet transmit queue completion descriptor
* @status: The status of the command (enum status_code)
* @comp_index: The index in the descriptor ring for which this
* is the completion.
@ -768,7 +768,7 @@ enum ionic_rxq_desc_opcode {
};
/**
* struct rxq_desc - Ethernet Rx queue descriptor format
* struct ionic_rxq_desc - Ethernet Rx queue descriptor format
* @opcode: Rx operation, see RXQ_DESC_OPCODE_*:
*
* RXQ_DESC_OPCODE_SIMPLE:
@ -789,7 +789,7 @@ struct ionic_rxq_desc {
};
/**
* struct rxq_sg_desc - Receive scatter-gather (SG) list
* struct ionic_rxq_sg_desc - Receive scatter-gather (SG) list
* @addr: DMA address of SG element data buffer
* @len: Length of SG element data buffer, in bytes
*/
@ -802,7 +802,7 @@ struct ionic_rxq_sg_desc {
};
/**
* struct rxq_comp - Ethernet receive queue completion descriptor
* struct ionic_rxq_comp - Ethernet receive queue completion descriptor
* @status: The status of the command (enum status_code)
* @num_sg_elems: Number of SG elements used by this descriptor
* @comp_index: The index in the descriptor ring for which this
@ -896,7 +896,7 @@ enum ionic_eth_hw_features {
};
/**
* struct q_control_cmd - Queue control command
* struct ionic_q_control_cmd - Queue control command
* @opcode: opcode
* @type: Queue type
* @lif_index: LIF index
@ -1033,8 +1033,8 @@ enum ionic_port_loopback_mode {
/**
* Transceiver Status information
* @state: Transceiver status (enum xcvr_state)
* @phy: Physical connection type (enum phy_type)
* @state: Transceiver status (enum ionic_xcvr_state)
* @phy: Physical connection type (enum ionic_phy_type)
* @pid: Transceiver link mode (enum pid)
* @sprom: Transceiver sprom contents
*/
@ -1051,9 +1051,9 @@ struct ionic_xcvr_status {
* @mtu: mtu
* @state: port admin state (enum port_admin_state)
* @an_enable: autoneg enable
* @fec_type: fec type (enum port_fec_type)
* @pause_type: pause type (enum port_pause_type)
* @loopback_mode: loopback mode (enum port_loopback_mode)
* @fec_type: fec type (enum ionic_port_fec_type)
* @pause_type: pause type (enum ionic_port_pause_type)
* @loopback_mode: loopback mode (enum ionic_port_loopback_mode)
*/
union ionic_port_config {
struct {
@ -1080,7 +1080,7 @@ union ionic_port_config {
/**
* Port Status information
* @status: link status (enum port_oper_status)
* @status: link status (enum ionic_port_oper_status)
* @id: port id
* @speed: link speed (in Mbps)
* @xcvr: tranceiver status
@ -1094,7 +1094,7 @@ struct ionic_port_status {
};
/**
* struct port_identify_cmd - Port identify command
* struct ionic_port_identify_cmd - Port identify command
* @opcode: opcode
* @index: port index
* @ver: Highest version of identify supported by driver
@ -1107,7 +1107,7 @@ struct ionic_port_identify_cmd {
};
/**
* struct port_identify_comp - Port identify command completion
* struct ionic_port_identify_comp - Port identify command completion
* @status: The status of the command (enum status_code)
* @ver: Version of identify returned by device
*/
@ -1118,10 +1118,10 @@ struct ionic_port_identify_comp {
};
/**
* struct port_init_cmd - Port initialization command
* struct ionic_port_init_cmd - Port initialization command
* @opcode: opcode
* @index: port index
* @info_pa: destination address for port info (struct port_info)
* @info_pa: destination address for port info (struct ionic_port_info)
*/
struct ionic_port_init_cmd {
u8 opcode;
@ -1132,7 +1132,7 @@ struct ionic_port_init_cmd {
};
/**
* struct port_init_comp - Port initialization command completion
* struct ionic_port_init_comp - Port initialization command completion
* @status: The status of the command (enum status_code)
*/
struct ionic_port_init_comp {
@ -1141,7 +1141,7 @@ struct ionic_port_init_comp {
};
/**
* struct port_reset_cmd - Port reset command
* struct ionic_port_reset_cmd - Port reset command
* @opcode: opcode
* @index: port index
*/
@ -1152,7 +1152,7 @@ struct ionic_port_reset_cmd {
};
/**
* struct port_reset_comp - Port reset command completion
* struct ionic_port_reset_comp - Port reset command completion
* @status: The status of the command (enum status_code)
*/
struct ionic_port_reset_comp {
@ -1183,7 +1183,7 @@ enum ionic_port_attr {
};
/**
* struct port_setattr_cmd - Set port attributes on the NIC
* struct ionic_port_setattr_cmd - Set port attributes on the NIC
* @opcode: Opcode
* @index: port index
* @attr: Attribute type (enum ionic_port_attr)
@ -1207,7 +1207,7 @@ struct ionic_port_setattr_cmd {
};
/**
* struct port_setattr_comp - Port set attr command completion
* struct ionic_port_setattr_comp - Port set attr command completion
* @status: The status of the command (enum status_code)
* @color: Color bit
*/
@ -1218,7 +1218,7 @@ struct ionic_port_setattr_comp {
};
/**
* struct port_getattr_cmd - Get port attributes from the NIC
* struct ionic_port_getattr_cmd - Get port attributes from the NIC
* @opcode: Opcode
* @index: port index
* @attr: Attribute type (enum ionic_port_attr)
@ -1231,7 +1231,7 @@ struct ionic_port_getattr_cmd {
};
/**
* struct port_getattr_comp - Port get attr command completion
* struct ionic_port_getattr_comp - Port get attr command completion
* @status: The status of the command (enum status_code)
* @color: Color bit
*/
@ -1252,10 +1252,10 @@ struct ionic_port_getattr_comp {
};
/**
* struct lif_status - Lif status register
* struct ionic_lif_status - Lif status register
* @eid: most recent NotifyQ event id
* @port_num: port the lif is connected to
* @link_status: port status (enum port_oper_status)
* @link_status: port status (enum ionic_port_oper_status)
* @link_speed: speed of link in Mbps
* @link_down_count: number of times link status changes
*/
@ -1270,7 +1270,7 @@ struct ionic_lif_status {
};
/**
* struct lif_reset_cmd - LIF reset command
* struct ionic_lif_reset_cmd - LIF reset command
* @opcode: opcode
* @index: LIF index
*/
@ -1290,7 +1290,7 @@ enum ionic_dev_state {
};
/**
* enum dev_attr - List of device attributes
* enum ionic_dev_attr - List of device attributes
*/
enum ionic_dev_attr {
IONIC_DEV_ATTR_STATE = 0,
@ -1299,10 +1299,10 @@ enum ionic_dev_attr {
};
/**
* struct dev_setattr_cmd - Set Device attributes on the NIC
* struct ionic_dev_setattr_cmd - Set Device attributes on the NIC
* @opcode: Opcode
* @attr: Attribute type (enum dev_attr)
* @state: Device state (enum dev_state)
* @attr: Attribute type (enum ionic_dev_attr)
* @state: Device state (enum ionic_dev_state)
* @name: The bus info, e.g. PCI slot-device-function, 0 terminated
* @features: Device features
*/
@ -1319,7 +1319,7 @@ struct ionic_dev_setattr_cmd {
};
/**
* struct dev_setattr_comp - Device set attr command completion
* struct ionic_dev_setattr_comp - Device set attr command completion
* @status: The status of the command (enum status_code)
* @features: Device features
* @color: Color bit
@ -1335,9 +1335,9 @@ struct ionic_dev_setattr_comp {
};
/**
* struct dev_getattr_cmd - Get Device attributes from the NIC
* struct ionic_dev_getattr_cmd - Get Device attributes from the NIC
* @opcode: opcode
* @attr: Attribute type (enum dev_attr)
* @attr: Attribute type (enum ionic_dev_attr)
*/
struct ionic_dev_getattr_cmd {
u8 opcode;
@ -1346,7 +1346,7 @@ struct ionic_dev_getattr_cmd {
};
/**
* struct dev_setattr_comp - Device set attr command completion
* struct ionic_dev_setattr_comp - Device set attr command completion
* @status: The status of the command (enum status_code)
* @features: Device features
* @color: Color bit
@ -1376,7 +1376,7 @@ enum ionic_rss_hash_types {
};
/**
* enum lif_attr - List of LIF attributes
* enum ionic_lif_attr - List of LIF attributes
*/
enum ionic_lif_attr {
IONIC_LIF_ATTR_STATE = 0,
@ -1389,15 +1389,15 @@ enum ionic_lif_attr {
};
/**
* struct lif_setattr_cmd - Set LIF attributes on the NIC
* struct ionic_lif_setattr_cmd - Set LIF attributes on the NIC
* @opcode: Opcode
* @type: Attribute type (enum lif_attr)
* @type: Attribute type (enum ionic_lif_attr)
* @index: LIF index
* @state: lif state (enum lif_state)
* @name: The netdev name string, 0 terminated
* @mtu: Mtu
* @mac: Station mac
* @features: Features (enum eth_hw_features)
* @features: Features (enum ionic_eth_hw_features)
* @rss: RSS properties
* @types: The hash types to enable (see rss_hash_types).
* @key: The hash secret key.
@ -1426,11 +1426,11 @@ struct ionic_lif_setattr_cmd {
};
/**
* struct lif_setattr_comp - LIF set attr command completion
* struct ionic_lif_setattr_comp - LIF set attr command completion
* @status: The status of the command (enum status_code)
* @comp_index: The index in the descriptor ring for which this
* is the completion.
* @features: features (enum eth_hw_features)
* @features: features (enum ionic_eth_hw_features)
* @color: Color bit
*/
struct ionic_lif_setattr_comp {
@ -1445,9 +1445,9 @@ struct ionic_lif_setattr_comp {
};
/**
* struct lif_getattr_cmd - Get LIF attributes from the NIC
* struct ionic_lif_getattr_cmd - Get LIF attributes from the NIC
* @opcode: Opcode
* @attr: Attribute type (enum lif_attr)
* @attr: Attribute type (enum ionic_lif_attr)
* @index: LIF index
*/
struct ionic_lif_getattr_cmd {
@ -1458,7 +1458,7 @@ struct ionic_lif_getattr_cmd {
};
/**
* struct lif_getattr_comp - LIF get attr command completion
* struct ionic_lif_getattr_comp - LIF get attr command completion
* @status: The status of the command (enum status_code)
* @comp_index: The index in the descriptor ring for which this
* is the completion.
@ -1466,7 +1466,7 @@ struct ionic_lif_getattr_cmd {
* @name: The netdev name string, 0 terminated
* @mtu: Mtu
* @mac: Station mac
* @features: Features (enum eth_hw_features)
* @features: Features (enum ionic_eth_hw_features)
* @color: Color bit
*/
struct ionic_lif_getattr_comp {
@ -1492,7 +1492,7 @@ enum ionic_rx_mode {
};
/**
* struct rx_mode_set_cmd - Set LIF's Rx mode command
* struct ionic_rx_mode_set_cmd - Set LIF's Rx mode command
* @opcode: opcode
* @lif_index: LIF index
* @rx_mode: Rx mode flags:
@ -1519,7 +1519,7 @@ enum ionic_rx_filter_match_type {
};
/**
* struct rx_filter_add_cmd - Add LIF Rx filter command
* struct ionic_rx_filter_add_cmd - Add LIF Rx filter command
* @opcode: opcode
* @qtype: Queue type
* @lif_index: LIF index
@ -1550,7 +1550,7 @@ struct ionic_rx_filter_add_cmd {
};
/**
* struct rx_filter_add_comp - Add LIF Rx filter command completion
* struct ionic_rx_filter_add_comp - Add LIF Rx filter command completion
* @status: The status of the command (enum status_code)
* @comp_index: The index in the descriptor ring for which this
* is the completion.
@ -1567,7 +1567,7 @@ struct ionic_rx_filter_add_comp {
};
/**
* struct rx_filter_del_cmd - Delete LIF Rx filter command
* struct ionic_rx_filter_del_cmd - Delete LIF Rx filter command
* @opcode: opcode
* @lif_index: LIF index
* @filter_id: Filter ID
@ -1583,7 +1583,7 @@ struct ionic_rx_filter_del_cmd {
typedef struct ionic_admin_comp ionic_rx_filter_del_comp;
/**
* struct qos_identify_cmd - QoS identify command
* struct ionic_qos_identify_cmd - QoS identify command
* @opcode: opcode
* @ver: Highest version of identify supported by driver
*
@ -1595,7 +1595,7 @@ struct ionic_qos_identify_cmd {
};
/**
* struct qos_identify_comp - QoS identify command completion
* struct ionic_qos_identify_comp - QoS identify command completion
* @status: The status of the command (enum status_code)
* @ver: Version of identify returned by device
*/
@ -1610,7 +1610,7 @@ struct ionic_qos_identify_comp {
#define IONIC_QOS_DSCP_MAX_VALUES 64
/**
* enum qos_class
* enum ionic_qos_class
*/
enum ionic_qos_class {
IONIC_QOS_CLASS_DEFAULT = 0,
@ -1623,7 +1623,7 @@ enum ionic_qos_class {
};
/**
* enum qos_class_type - Traffic classification criteria
* enum ionic_qos_class_type - Traffic classification criteria
*/
enum ionic_qos_class_type {
IONIC_QOS_CLASS_TYPE_NONE = 0,
@ -1632,7 +1632,7 @@ enum ionic_qos_class_type {
};
/**
* enum qos_sched_type - Qos class scheduling type
* enum ionic_qos_sched_type - Qos class scheduling type
*/
enum ionic_qos_sched_type {
IONIC_QOS_SCHED_TYPE_STRICT = 0, /* Strict priority */
@ -1640,15 +1640,15 @@ enum ionic_qos_sched_type {
};
/**
* union qos_config - Qos configuration structure
* union ionic_qos_config - Qos configuration structure
* @flags: Configuration flags
* IONIC_QOS_CONFIG_F_ENABLE enable
* IONIC_QOS_CONFIG_F_DROP drop/nodrop
* IONIC_QOS_CONFIG_F_RW_DOT1Q_PCP enable dot1q pcp rewrite
* IONIC_QOS_CONFIG_F_RW_IP_DSCP enable ip dscp rewrite
* @sched_type: Qos class scheduling type (enum qos_sched_type)
* @class_type: Qos class type (enum qos_class_type)
* @pause_type: Qos pause type (enum qos_pause_type)
* @sched_type: Qos class scheduling type (enum ionic_qos_sched_type)
* @class_type: Qos class type (enum ionic_qos_class_type)
* @pause_type: Qos pause type (enum ionic_qos_pause_type)
* @name: Qos class name
* @mtu: MTU of the class
* @pfc_dot1q_pcp: Pcp value for pause frames (valid iff F_NODROP)
@ -1697,7 +1697,7 @@ union ionic_qos_config {
};
/**
* union qos_identity - QoS identity structure
* union ionic_qos_identity - QoS identity structure
* @version: Version of the identify structure
* @type: QoS system type
* @nclasses: Number of usable QoS classes
@ -1730,7 +1730,7 @@ struct ionic_qos_init_cmd {
typedef struct ionic_admin_comp ionic_qos_init_comp;
/**
* struct qos_reset_cmd - Qos config reset command
* struct ionic_qos_reset_cmd - Qos config reset command
* @opcode: Opcode
*/
struct ionic_qos_reset_cmd {
@ -1742,7 +1742,7 @@ struct ionic_qos_reset_cmd {
typedef struct ionic_admin_comp ionic_qos_reset_comp;
/**
* struct fw_download_cmd - Firmware download command
* struct ionic_fw_download_cmd - Firmware download command
* @opcode: opcode
* @addr: dma address of the firmware buffer
* @offset: offset of the firmware buffer within the full image
@ -1765,9 +1765,9 @@ enum ionic_fw_control_oper {
};
/**
* struct fw_control_cmd - Firmware control command
* struct ionic_fw_control_cmd - Firmware control command
* @opcode: opcode
* @oper: firmware control operation (enum fw_control_oper)
* @oper: firmware control operation (enum ionic_fw_control_oper)
* @slot: slot to activate
*/
struct ionic_fw_control_cmd {
@ -1779,7 +1779,7 @@ struct ionic_fw_control_cmd {
};
/**
* struct fw_control_comp - Firmware control copletion
* struct ionic_fw_control_comp - Firmware control copletion
* @opcode: opcode
* @slot: slot where the firmware was installed
*/
@ -1797,13 +1797,13 @@ struct ionic_fw_control_comp {
******************************************************************/
/**
* struct rdma_reset_cmd - Reset RDMA LIF cmd
* struct ionic_rdma_reset_cmd - Reset RDMA LIF cmd
* @opcode: opcode
* @lif_index: lif index
*
* There is no rdma specific dev command completion struct. Completion uses
* the common struct admin_comp. Only the status is indicated. Nonzero status
* means the LIF does not support rdma.
* the common struct ionic_admin_comp. Only the status is indicated.
* Nonzero status means the LIF does not support rdma.
**/
struct ionic_rdma_reset_cmd {
u8 opcode;
@ -1813,7 +1813,7 @@ struct ionic_rdma_reset_cmd {
};
/**
* struct rdma_queue_cmd - Create RDMA Queue command
* struct ionic_rdma_queue_cmd - Create RDMA Queue command
* @opcode: opcode, 52, 53
* @lif_index lif index
* @qid_ver: (qid | (rdma version << 24))
@ -1839,7 +1839,7 @@ struct ionic_rdma_reset_cmd {
* memory registration.
*
* There is no rdma specific dev command completion struct. Completion uses
* the common struct admin_comp. Only the status is indicated.
* the common struct ionic_admin_comp. Only the status is indicated.
**/
struct ionic_rdma_queue_cmd {
u8 opcode;
@ -1860,7 +1860,7 @@ struct ionic_rdma_queue_cmd {
******************************************************************/
/**
* struct notifyq_event
* struct ionic_notifyq_event
* @eid: event number
* @ecode: event code
* @data: unspecified data about the event
@ -1875,7 +1875,7 @@ struct ionic_notifyq_event {
};
/**
* struct link_change_event
* struct ionic_link_change_event
* @eid: event number
* @ecode: event code = EVENT_OPCODE_LINK_CHANGE
* @link_status: link up or down, with error bits (enum port_status)
@ -1892,7 +1892,7 @@ struct ionic_link_change_event {
};
/**
* struct reset_event
* struct ionic_reset_event
* @eid: event number
* @ecode: event code = EVENT_OPCODE_RESET
* @reset_code: reset type
@ -1910,7 +1910,7 @@ struct ionic_reset_event {
};
/**
* struct heartbeat_event
* struct ionic_heartbeat_event
* @eid: event number
* @ecode: event code = EVENT_OPCODE_HEARTBEAT
*
@ -1923,7 +1923,7 @@ struct ionic_heartbeat_event {
};
/**
* struct log_event
* struct ionic_log_event
* @eid: event number
* @ecode: event code = EVENT_OPCODE_LOG
* @data: log data
@ -1937,7 +1937,7 @@ struct ionic_log_event {
};
/**
* struct port_stats
* struct ionic_port_stats
*/
struct ionic_port_stats {
__le64 frames_rx_ok;
@ -2067,7 +2067,7 @@ struct ionic_mgmt_port_stats {
};
/**
* struct port_identity - port identity structure
* struct ionic_port_identity - port identity structure
* @version: identity structure version
* @type: type of port (enum port_type)
* @num_lanes: number of lanes for the port
@ -2099,7 +2099,7 @@ union ionic_port_identity {
};
/**
* struct port_info - port info structure
* struct ionic_port_info - port info structure
* @port_status: port status
* @port_stats: port stats
*/
@ -2110,7 +2110,7 @@ struct ionic_port_info {
};
/**
* struct lif_stats
* struct ionic_lif_stats
*/
struct ionic_lif_stats {
/* RX */
@ -2264,7 +2264,7 @@ struct ionic_lif_stats {
};
/**
* struct lif_info - lif info structure
* struct ionic_lif_info - lif info structure
*/
struct ionic_lif_info {
union ionic_lif_config config;
@ -2357,7 +2357,7 @@ union ionic_dev_info_regs {
};
/**
* union dev_cmd_regs - Device command register format (read-write)
* union ionic_dev_cmd_regs - Device command register format (read-write)
* @doorbell: Device Cmd Doorbell, write-only.
* Write a 1 to signal device to process cmd,
* poll done for completion.
@ -2379,7 +2379,7 @@ union ionic_dev_cmd_regs {
};
/**
* union dev_regs - Device register format in for bar 0 page 0
* union ionic_dev_regs - Device register format in for bar 0 page 0
* @info: Device info registers
* @devcmd: Device command registers
*/
@ -2433,7 +2433,7 @@ union ionic_adminq_comp {
#define IONIC_ASIC_TYPE_CAPRI 0
/**
* struct doorbell - Doorbell register layout
* struct ionic_doorbell - Doorbell register layout
* @p_index: Producer index
* @ring: Selects the specific ring of the queue to update.
* Type-specific meaning:

View File

@ -622,12 +622,14 @@ static int ionic_lif_rxq_init(struct ionic_lif *lif, struct ionic_qcq *qcq)
.lif_index = cpu_to_le16(lif->index),
.type = q->type,
.index = cpu_to_le32(q->index),
.flags = cpu_to_le16(IONIC_QINIT_F_IRQ),
.flags = cpu_to_le16(IONIC_QINIT_F_IRQ |
IONIC_QINIT_F_SG),
.intr_index = cpu_to_le16(cq->bound_intr->index),
.pid = cpu_to_le16(q->pid),
.ring_size = ilog2(q->num_descs),
.ring_base = cpu_to_le64(q->base_pa),
.cq_ring_base = cpu_to_le64(cq->base_pa),
.sg_ring_base = cpu_to_le64(q->sg_base_pa),
},
};
int err;
@ -1460,13 +1462,14 @@ static int ionic_txrx_alloc(struct ionic_lif *lif)
lif->txqcqs[i].qcq->stats = lif->txqcqs[i].stats;
}
flags = IONIC_QCQ_F_RX_STATS | IONIC_QCQ_F_INTR;
flags = IONIC_QCQ_F_RX_STATS | IONIC_QCQ_F_SG | IONIC_QCQ_F_INTR;
for (i = 0; i < lif->nxqs; i++) {
err = ionic_qcq_alloc(lif, IONIC_QTYPE_RXQ, i, "rx", flags,
lif->nrxq_descs,
sizeof(struct ionic_rxq_desc),
sizeof(struct ionic_rxq_comp),
0, lif->kern_pid, &lif->rxqcqs[i].qcq);
sizeof(struct ionic_rxq_sg_desc),
lif->kern_pid, &lif->rxqcqs[i].qcq);
if (err)
goto err_out;
@ -1686,7 +1689,7 @@ static struct ionic_lif *ionic_lif_alloc(struct ionic *ionic, unsigned int index
/* Convert the default coalesce value to actual hw resolution */
lif->rx_coalesce_usecs = IONIC_ITR_COAL_USEC_DEFAULT;
lif->rx_coalesce_hw = ionic_coal_hw_to_usec(lif->ionic,
lif->rx_coalesce_hw = ionic_coal_usec_to_hw(lif->ionic,
lif->rx_coalesce_usecs);
snprintf(lif->name, sizeof(lif->name), "lif%u", index);

View File

@ -245,6 +245,10 @@ static int ionic_adminq_post(struct ionic_lif *lif, struct ionic_admin_ctx *ctx)
goto err_out;
}
err = ionic_heartbeat_check(lif->ionic);
if (err)
goto err_out;
memcpy(adminq->head->desc, &ctx->cmd, sizeof(ctx->cmd));
dev_dbg(&lif->netdev->dev, "post admin queue command:\n");
@ -305,6 +309,14 @@ int ionic_napi(struct napi_struct *napi, int budget, ionic_cq_cb cb,
return work_done;
}
static void ionic_dev_cmd_clean(struct ionic *ionic)
{
union ionic_dev_cmd_regs *regs = ionic->idev.dev_cmd_regs;
iowrite32(0, &regs->doorbell);
memset_io(&regs->cmd, 0, sizeof(regs->cmd));
}
int ionic_dev_cmd_wait(struct ionic *ionic, unsigned long max_seconds)
{
struct ionic_dev *idev = &ionic->idev;
@ -314,6 +326,7 @@ int ionic_dev_cmd_wait(struct ionic *ionic, unsigned long max_seconds)
int opcode;
int done;
int err;
int hb;
WARN_ON(in_interrupt());
@ -328,7 +341,8 @@ try_again:
if (done)
break;
msleep(20);
} while (!done && time_before(jiffies, max_wait));
hb = ionic_heartbeat_check(ionic);
} while (!done && !hb && time_before(jiffies, max_wait));
duration = jiffies - start_time;
opcode = idev->dev_cmd_regs->cmd.cmd.opcode;
@ -336,7 +350,15 @@ try_again:
ionic_opcode_to_str(opcode), opcode,
done, duration / HZ, duration);
if (!done && hb) {
ionic_dev_cmd_clean(ionic);
dev_warn(ionic->dev, "DEVCMD %s (%d) failed - FW halted\n",
ionic_opcode_to_str(opcode), opcode);
return -ENXIO;
}
if (!done && !time_before(jiffies, max_wait)) {
ionic_dev_cmd_clean(ionic);
dev_warn(ionic->dev, "DEVCMD %s (%d) timeout after %ld secs\n",
ionic_opcode_to_str(opcode), opcode, max_seconds);
return -ETIMEDOUT;

View File

@ -34,52 +34,110 @@ static inline struct netdev_queue *q_to_ndq(struct ionic_queue *q)
return netdev_get_tx_queue(q->lif->netdev, q->index);
}
static void ionic_rx_recycle(struct ionic_queue *q, struct ionic_desc_info *desc_info,
struct sk_buff *skb)
static struct sk_buff *ionic_rx_skb_alloc(struct ionic_queue *q,
unsigned int len, bool frags)
{
struct ionic_rxq_desc *old = desc_info->desc;
struct ionic_rxq_desc *new = q->head->desc;
struct ionic_lif *lif = q->lif;
struct ionic_rx_stats *stats;
struct net_device *netdev;
struct sk_buff *skb;
new->addr = old->addr;
new->len = old->len;
netdev = lif->netdev;
stats = q_to_rx_stats(q);
ionic_rxq_post(q, true, ionic_rx_clean, skb);
if (frags)
skb = napi_get_frags(&q_to_qcq(q)->napi);
else
skb = netdev_alloc_skb_ip_align(netdev, len);
if (unlikely(!skb)) {
net_warn_ratelimited("%s: SKB alloc failed on %s!\n",
netdev->name, q->name);
stats->alloc_err++;
return NULL;
}
return skb;
}
static bool ionic_rx_copybreak(struct ionic_queue *q, struct ionic_desc_info *desc_info,
struct ionic_cq_info *cq_info, struct sk_buff **skb)
static struct sk_buff *ionic_rx_frags(struct ionic_queue *q,
struct ionic_desc_info *desc_info,
struct ionic_cq_info *cq_info)
{
struct ionic_rxq_comp *comp = cq_info->cq_desc;
struct ionic_rxq_desc *desc = desc_info->desc;
struct net_device *netdev = q->lif->netdev;
struct device *dev = q->lif->ionic->dev;
struct sk_buff *new_skb;
u16 clen, dlen;
struct ionic_page_info *page_info;
struct sk_buff *skb;
unsigned int i;
u16 frag_len;
u16 len;
clen = le16_to_cpu(comp->len);
dlen = le16_to_cpu(desc->len);
if (clen > q->lif->rx_copybreak) {
dma_unmap_single(dev, (dma_addr_t)le64_to_cpu(desc->addr),
dlen, DMA_FROM_DEVICE);
return false;
page_info = &desc_info->pages[0];
len = le16_to_cpu(comp->len);
prefetch(page_address(page_info->page) + NET_IP_ALIGN);
skb = ionic_rx_skb_alloc(q, len, true);
if (unlikely(!skb))
return NULL;
i = comp->num_sg_elems + 1;
do {
if (unlikely(!page_info->page)) {
struct napi_struct *napi = &q_to_qcq(q)->napi;
napi->skb = NULL;
dev_kfree_skb(skb);
return NULL;
}
frag_len = min(len, (u16)PAGE_SIZE);
len -= frag_len;
dma_unmap_page(dev, dma_unmap_addr(page_info, dma_addr),
PAGE_SIZE, DMA_FROM_DEVICE);
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
page_info->page, 0, frag_len, PAGE_SIZE);
page_info->page = NULL;
page_info++;
i--;
} while (i > 0);
return skb;
}
static struct sk_buff *ionic_rx_copybreak(struct ionic_queue *q,
struct ionic_desc_info *desc_info,
struct ionic_cq_info *cq_info)
{
struct ionic_rxq_comp *comp = cq_info->cq_desc;
struct device *dev = q->lif->ionic->dev;
struct ionic_page_info *page_info;
struct sk_buff *skb;
u16 len;
page_info = &desc_info->pages[0];
len = le16_to_cpu(comp->len);
skb = ionic_rx_skb_alloc(q, len, false);
if (unlikely(!skb))
return NULL;
if (unlikely(!page_info->page)) {
dev_kfree_skb(skb);
return NULL;
}
new_skb = netdev_alloc_skb_ip_align(netdev, clen);
if (!new_skb) {
dma_unmap_single(dev, (dma_addr_t)le64_to_cpu(desc->addr),
dlen, DMA_FROM_DEVICE);
return false;
}
dma_sync_single_for_cpu(dev, dma_unmap_addr(page_info, dma_addr),
len, DMA_FROM_DEVICE);
skb_copy_to_linear_data(skb, page_address(page_info->page), len);
dma_sync_single_for_device(dev, dma_unmap_addr(page_info, dma_addr),
len, DMA_FROM_DEVICE);
dma_sync_single_for_cpu(dev, (dma_addr_t)le64_to_cpu(desc->addr),
clen, DMA_FROM_DEVICE);
skb_put(skb, len);
skb->protocol = eth_type_trans(skb, q->lif->netdev);
memcpy(new_skb->data, (*skb)->data, clen);
ionic_rx_recycle(q, desc_info, *skb);
*skb = new_skb;
return true;
return skb;
}
static void ionic_rx_clean(struct ionic_queue *q, struct ionic_desc_info *desc_info,
@ -87,35 +145,34 @@ static void ionic_rx_clean(struct ionic_queue *q, struct ionic_desc_info *desc_i
{
struct ionic_rxq_comp *comp = cq_info->cq_desc;
struct ionic_qcq *qcq = q_to_qcq(q);
struct sk_buff *skb = cb_arg;
struct ionic_rx_stats *stats;
struct net_device *netdev;
struct sk_buff *skb;
stats = q_to_rx_stats(q);
netdev = q->lif->netdev;
if (comp->status) {
ionic_rx_recycle(q, desc_info, skb);
if (comp->status)
return;
}
if (unlikely(test_bit(IONIC_LIF_QUEUE_RESET, q->lif->state))) {
/* no packet processing while resetting */
ionic_rx_recycle(q, desc_info, skb);
/* no packet processing while resetting */
if (unlikely(test_bit(IONIC_LIF_QUEUE_RESET, q->lif->state)))
return;
}
stats->pkts++;
stats->bytes += le16_to_cpu(comp->len);
ionic_rx_copybreak(q, desc_info, cq_info, &skb);
if (le16_to_cpu(comp->len) <= q->lif->rx_copybreak)
skb = ionic_rx_copybreak(q, desc_info, cq_info);
else
skb = ionic_rx_frags(q, desc_info, cq_info);
skb_put(skb, le16_to_cpu(comp->len));
skb->protocol = eth_type_trans(skb, netdev);
if (unlikely(!skb))
return;
skb_record_rx_queue(skb, q->index);
if (netdev->features & NETIF_F_RXHASH) {
if (likely(netdev->features & NETIF_F_RXHASH)) {
switch (comp->pkt_type_color & IONIC_RXQ_COMP_PKT_TYPE_MASK) {
case IONIC_PKT_TYPE_IPV4:
case IONIC_PKT_TYPE_IPV6:
@ -132,7 +189,7 @@ static void ionic_rx_clean(struct ionic_queue *q, struct ionic_desc_info *desc_i
}
}
if (netdev->features & NETIF_F_RXCSUM) {
if (likely(netdev->features & NETIF_F_RXCSUM)) {
if (comp->csum_flags & IONIC_RXQ_COMP_CSUM_F_CALC) {
skb->ip_summed = CHECKSUM_COMPLETE;
skb->csum = (__wsum)le16_to_cpu(comp->csum);
@ -142,18 +199,21 @@ static void ionic_rx_clean(struct ionic_queue *q, struct ionic_desc_info *desc_i
stats->csum_none++;
}
if ((comp->csum_flags & IONIC_RXQ_COMP_CSUM_F_TCP_BAD) ||
(comp->csum_flags & IONIC_RXQ_COMP_CSUM_F_UDP_BAD) ||
(comp->csum_flags & IONIC_RXQ_COMP_CSUM_F_IP_BAD))
if (unlikely((comp->csum_flags & IONIC_RXQ_COMP_CSUM_F_TCP_BAD) ||
(comp->csum_flags & IONIC_RXQ_COMP_CSUM_F_UDP_BAD) ||
(comp->csum_flags & IONIC_RXQ_COMP_CSUM_F_IP_BAD)))
stats->csum_error++;
if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) {
if (likely(netdev->features & NETIF_F_HW_VLAN_CTAG_RX)) {
if (comp->csum_flags & IONIC_RXQ_COMP_CSUM_F_VLAN)
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
le16_to_cpu(comp->vlan_tci));
}
napi_gro_receive(&qcq->napi, skb);
if (le16_to_cpu(comp->len) <= q->lif->rx_copybreak)
napi_gro_receive(&qcq->napi, skb);
else
napi_gro_frags(&qcq->napi);
}
static bool ionic_rx_service(struct ionic_cq *cq, struct ionic_cq_info *cq_info)
@ -213,66 +273,125 @@ void ionic_rx_flush(struct ionic_cq *cq)
work_done, IONIC_INTR_CRED_RESET_COALESCE);
}
static struct sk_buff *ionic_rx_skb_alloc(struct ionic_queue *q, unsigned int len,
dma_addr_t *dma_addr)
static struct page *ionic_rx_page_alloc(struct ionic_queue *q,
dma_addr_t *dma_addr)
{
struct ionic_lif *lif = q->lif;
struct ionic_rx_stats *stats;
struct net_device *netdev;
struct sk_buff *skb;
struct device *dev;
struct page *page;
netdev = lif->netdev;
dev = lif->ionic->dev;
stats = q_to_rx_stats(q);
skb = netdev_alloc_skb_ip_align(netdev, len);
if (!skb) {
net_warn_ratelimited("%s: SKB alloc failed on %s!\n",
netdev->name, q->name);
page = alloc_page(GFP_ATOMIC);
if (unlikely(!page)) {
net_err_ratelimited("%s: Page alloc failed on %s!\n",
netdev->name, q->name);
stats->alloc_err++;
return NULL;
}
*dma_addr = dma_map_single(dev, skb->data, len, DMA_FROM_DEVICE);
if (dma_mapping_error(dev, *dma_addr)) {
dev_kfree_skb(skb);
net_warn_ratelimited("%s: DMA single map failed on %s!\n",
netdev->name, q->name);
*dma_addr = dma_map_page(dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE);
if (unlikely(dma_mapping_error(dev, *dma_addr))) {
__free_page(page);
net_err_ratelimited("%s: DMA single map failed on %s!\n",
netdev->name, q->name);
stats->dma_map_err++;
return NULL;
}
return skb;
return page;
}
#define IONIC_RX_RING_DOORBELL_STRIDE ((1 << 2) - 1)
static void ionic_rx_page_free(struct ionic_queue *q, struct page *page,
dma_addr_t dma_addr)
{
struct ionic_lif *lif = q->lif;
struct net_device *netdev;
struct device *dev;
netdev = lif->netdev;
dev = lif->ionic->dev;
if (unlikely(!page)) {
net_err_ratelimited("%s: Trying to free unallocated buffer on %s!\n",
netdev->name, q->name);
return;
}
dma_unmap_page(dev, dma_addr, PAGE_SIZE, DMA_FROM_DEVICE);
__free_page(page);
}
#define IONIC_RX_RING_DOORBELL_STRIDE ((1 << 5) - 1)
#define IONIC_RX_RING_HEAD_BUF_SZ 2048
void ionic_rx_fill(struct ionic_queue *q)
{
struct net_device *netdev = q->lif->netdev;
struct ionic_desc_info *desc_info;
struct ionic_page_info *page_info;
struct ionic_rxq_sg_desc *sg_desc;
struct ionic_rxq_sg_elem *sg_elem;
struct ionic_rxq_desc *desc;
struct sk_buff *skb;
dma_addr_t dma_addr;
unsigned int nfrags;
bool ring_doorbell;
unsigned int i, j;
unsigned int len;
unsigned int i;
len = netdev->mtu + ETH_HLEN;
nfrags = round_up(len, PAGE_SIZE) / PAGE_SIZE;
for (i = ionic_q_space_avail(q); i; i--) {
skb = ionic_rx_skb_alloc(q, len, &dma_addr);
if (!skb)
return;
desc_info = q->head;
desc = desc_info->desc;
sg_desc = desc_info->sg_desc;
page_info = &desc_info->pages[0];
desc = q->head->desc;
desc->addr = cpu_to_le64(dma_addr);
desc->len = cpu_to_le16(len);
desc->opcode = IONIC_RXQ_DESC_OPCODE_SIMPLE;
if (page_info->page) { /* recycle the buffer */
ring_doorbell = ((q->head->index + 1) &
IONIC_RX_RING_DOORBELL_STRIDE) == 0;
ionic_rxq_post(q, ring_doorbell, ionic_rx_clean, NULL);
continue;
}
/* fill main descriptor - pages[0] */
desc->opcode = (nfrags > 1) ? IONIC_RXQ_DESC_OPCODE_SG :
IONIC_RXQ_DESC_OPCODE_SIMPLE;
desc_info->npages = nfrags;
page_info->page = ionic_rx_page_alloc(q, &page_info->dma_addr);
if (unlikely(!page_info->page)) {
desc->addr = 0;
desc->len = 0;
return;
}
desc->addr = cpu_to_le64(page_info->dma_addr);
desc->len = cpu_to_le16(PAGE_SIZE);
page_info++;
/* fill sg descriptors - pages[1..n] */
for (j = 0; j < nfrags - 1; j++) {
if (page_info->page) /* recycle the sg buffer */
continue;
sg_elem = &sg_desc->elems[j];
page_info->page = ionic_rx_page_alloc(q, &page_info->dma_addr);
if (unlikely(!page_info->page)) {
sg_elem->addr = 0;
sg_elem->len = 0;
return;
}
sg_elem->addr = cpu_to_le64(page_info->dma_addr);
sg_elem->len = cpu_to_le16(PAGE_SIZE);
page_info++;
}
ring_doorbell = ((q->head->index + 1) &
IONIC_RX_RING_DOORBELL_STRIDE) == 0;
ionic_rxq_post(q, ring_doorbell, ionic_rx_clean, skb);
ionic_rxq_post(q, ring_doorbell, ionic_rx_clean, NULL);
}
}
@ -283,15 +402,26 @@ static void ionic_rx_fill_cb(void *arg)
void ionic_rx_empty(struct ionic_queue *q)
{
struct device *dev = q->lif->ionic->dev;
struct ionic_rxq_sg_desc *sg_desc;
struct ionic_desc_info *cur;
struct ionic_rxq_desc *desc;
unsigned int i;
for (cur = q->tail; cur != q->head; cur = cur->next) {
desc = cur->desc;
dma_unmap_single(dev, le64_to_cpu(desc->addr),
le16_to_cpu(desc->len), DMA_FROM_DEVICE);
dev_kfree_skb(cur->cb_arg);
desc->addr = 0;
desc->len = 0;
sg_desc = cur->sg_desc;
for (i = 0; i < cur->npages; i++) {
if (likely(cur->pages[i].page)) {
ionic_rx_page_free(q, cur->pages[i].page,
cur->pages[i].dma_addr);
cur->pages[i].page = NULL;
cur->pages[i].dma_addr = 0;
}
}
cur->cb_arg = NULL;
}
}