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:
commit
0629d2456a
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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, ®s->doorbell);
|
||||
memset_io(®s->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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue