Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bd3f5433 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'qlcnic'



Himanshu Madhani says:

====================
This series contains following patches

o in v2 series, we received feedback on return codes to use standard error
  codes instead of mixing custom error codes. We have modified patch for
  loopback diagnostic test to return standard error codes.

o rest of the 3 patches in the series are for mailbox refactoring

  Current driver-firmware mailbox interface was operating in polling mode
  because of some limitations with the earlier versions of 83xx adapter
  firmware. These issues are resolved now and we are implementing the
  mailbox interface in interrupt mode.

  There are three patches which refactors mailbox handling:
  * Interrupt mode mailbox implantation.
  * Replace poll mode mailbox interfaces with interrupt mode interfaces.
  * Operate mailbox in poll mode when interrupts are not available.

changes from v2 -> v3
 * Addressed review feedback to use standard return codes for loopback
   diagnostic test.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents a594e4f8 37534567
Loading
Loading
Loading
Loading
+46 −13
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@
#include <linux/tcp.h>
#include <linux/skbuff.h>
#include <linux/firmware.h>

#include <linux/ethtool.h>
#include <linux/mii.h>
#include <linux/timer.h>
@@ -38,8 +37,8 @@

#define _QLCNIC_LINUX_MAJOR 5
#define _QLCNIC_LINUX_MINOR 2
#define _QLCNIC_LINUX_SUBVERSION 44
#define QLCNIC_LINUX_VERSIONID  "5.2.44"
#define _QLCNIC_LINUX_SUBVERSION 45
#define QLCNIC_LINUX_VERSIONID  "5.2.45"
#define QLCNIC_DRV_IDC_VER  0x01
#define QLCNIC_DRIVER_VERSION  ((_QLCNIC_LINUX_MAJOR << 16) |\
		 (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
@@ -467,7 +466,7 @@ struct qlcnic_hardware_context {
	u32 *ext_reg_tbl;
	u32 mbox_aen[QLC_83XX_MBX_AEN_CNT];
	u32 mbox_reg[4];
	spinlock_t mbx_lock;
	struct qlcnic_mailbox *mailbox;
};

struct qlcnic_adapter_stats {
@@ -950,12 +949,6 @@ struct qlcnic_ipaddr {
#define QLCNIC_READD_AGE	20
#define QLCNIC_LB_MAX_FILTERS	64
#define QLCNIC_LB_BUCKET_SIZE	32

/* QLCNIC Driver Error Code */
#define QLCNIC_FW_NOT_RESPOND		51
#define QLCNIC_TEST_IN_PROGRESS		52
#define QLCNIC_UNDEFINED_ERROR		53
#define QLCNIC_LB_CABLE_NOT_CONN	54
#define QLCNIC_ILB_MAX_RCV_LOOP	10

struct qlcnic_filter {
@@ -972,6 +965,21 @@ struct qlcnic_filter_hash {
	u16 fbucket_size;
};

/* Mailbox specific data structures */
struct qlcnic_mailbox {
	struct workqueue_struct	*work_q;
	struct qlcnic_adapter	*adapter;
	struct qlcnic_mbx_ops	*ops;
	struct work_struct	work;
	struct completion	completion;
	struct list_head	cmd_q;
	unsigned long		status;
	spinlock_t		queue_lock;	/* Mailbox queue lock */
	spinlock_t		aen_lock;	/* Mailbox response/AEN lock */
	atomic_t		rsp_status;
	u32			num_cmds;
};

struct qlcnic_adapter {
	struct qlcnic_hardware_context *ahw;
	struct qlcnic_recv_context *recv_ctx;
@@ -1385,9 +1393,20 @@ struct _cdrp_cmd {
};

struct qlcnic_cmd_args {
	struct completion	completion;
	struct list_head	list;
	struct _cdrp_cmd	req;
	struct _cdrp_cmd	rsp;
	int op_type;
	atomic_t		rsp_status;
	int			pay_size;
	u32			rsp_opcode;
	u32			total_cmds;
	u32			op_type;
	u32			type;
	u32			cmd_op;
	u32			*hdr;	/* Back channel message header */
	u32			*pay;	/* Back channel message payload */
	u8			func_num;
};

int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter);
@@ -1600,6 +1619,20 @@ struct qlcnic_nic_template {
	int (*resume)(struct qlcnic_adapter *);
};

struct qlcnic_mbx_ops {
	int (*enqueue_cmd) (struct qlcnic_adapter *,
			    struct qlcnic_cmd_args *, unsigned long *);
	void (*dequeue_cmd) (struct qlcnic_adapter *, struct qlcnic_cmd_args *);
	void (*decode_resp) (struct qlcnic_adapter *, struct qlcnic_cmd_args *);
	void (*encode_cmd) (struct qlcnic_adapter *, struct qlcnic_cmd_args *);
	void (*nofity_fw) (struct qlcnic_adapter *, u8);
};

int qlcnic_83xx_init_mailbox_work(struct qlcnic_adapter *);
void qlcnic_83xx_detach_mailbox_work(struct qlcnic_adapter *);
void qlcnic_83xx_reinit_mbx_work(struct qlcnic_mailbox *mbx);
void qlcnic_83xx_free_mailbox(struct qlcnic_mailbox *mbx);

/* Adapter hardware abstraction */
struct qlcnic_hardware_ops {
	void (*read_crb) (struct qlcnic_adapter *, char *, loff_t, size_t);
+459 −156

File changed.

Preview size limit exceeded, changes collapsed.

+23 −4
Original line number Diff line number Diff line
@@ -89,6 +89,13 @@

#define QLC_83XX_MAX_RESET_SEQ_ENTRIES	16

#define QLC_83XX_MBX_POST_BC_OP		0x1
#define QLC_83XX_MBX_COMPLETION		0x0
#define QLC_83XX_MBX_REQUEST		0x1

#define QLC_83XX_MBX_TIMEOUT		(5 * HZ)
#define QLC_83XX_MBX_CMD_LOOP		5000000

/* status descriptor mailbox data
 * @phy_addr_{low|high}: physical address of buffer
 * @sds_ring_size: buffer size
@@ -449,6 +456,20 @@ enum qlcnic_83xx_states {
#define QLC_83xx_FLASH_MAX_WAIT_USEC		100
#define QLC_83XX_FLASH_LOCK_TIMEOUT		10000

enum qlc_83xx_mbx_cmd_type {
	QLC_83XX_MBX_CMD_WAIT = 0,
	QLC_83XX_MBX_CMD_NO_WAIT,
	QLC_83XX_MBX_CMD_BUSY_WAIT,
};

enum qlc_83xx_mbx_response_states {
	QLC_83XX_MBX_RESPONSE_WAIT = 0,
	QLC_83XX_MBX_RESPONSE_ARRIVED,
};

#define QLC_83XX_MBX_RESPONSE_FAILED	0x2
#define QLC_83XX_MBX_RESPONSE_UNKNOWN	0x3

/* Additional registers in 83xx */
enum qlc_83xx_ext_regs {
	QLCNIC_GLOBAL_RESET = 0,
@@ -498,7 +519,7 @@ enum qlc_83xx_ext_regs {

/* 83xx funcitons */
int qlcnic_83xx_get_fw_version(struct qlcnic_adapter *);
int qlcnic_83xx_mbx_op(struct qlcnic_adapter *, struct qlcnic_cmd_args *);
int qlcnic_83xx_issue_cmd(struct qlcnic_adapter *, struct qlcnic_cmd_args *);
int qlcnic_83xx_setup_intr(struct qlcnic_adapter *, u8);
void qlcnic_83xx_get_func_no(struct qlcnic_adapter *);
int qlcnic_83xx_cam_lock(struct qlcnic_adapter *);
@@ -551,7 +572,7 @@ void qlcnic_set_npar_data(struct qlcnic_adapter *, const struct qlcnic_info *,
void qlcnic_83xx_config_intr_coal(struct qlcnic_adapter *);
irqreturn_t qlcnic_83xx_handle_aen(int, void *);
int qlcnic_83xx_get_port_info(struct qlcnic_adapter *);
void qlcnic_83xx_enable_mbx_intrpt(struct qlcnic_adapter *);
void qlcnic_83xx_enable_mbx_interrupt(struct qlcnic_adapter *);
void qlcnic_83xx_disable_mbx_intr(struct qlcnic_adapter *);
irqreturn_t qlcnic_83xx_clear_legacy_intr(struct qlcnic_adapter *);
irqreturn_t qlcnic_83xx_intr(int, void *);
@@ -623,8 +644,6 @@ int qlcnic_83xx_set_led(struct net_device *, enum ethtool_phys_id_state);
int qlcnic_83xx_flash_test(struct qlcnic_adapter *);
int qlcnic_83xx_enable_flash_write(struct qlcnic_adapter *);
int qlcnic_83xx_disable_flash_write(struct qlcnic_adapter *);
u32 qlcnic_83xx_mac_rcode(struct qlcnic_adapter *);
u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *, u32 *);
void qlcnic_83xx_enable_mbx_poll(struct qlcnic_adapter *);
void qlcnic_83xx_disable_mbx_poll(struct qlcnic_adapter *);
void qlcnic_83xx_set_mac_filter_count(struct qlcnic_adapter *);
+62 −21
Original line number Diff line number Diff line
@@ -399,6 +399,7 @@ static void qlcnic_83xx_idc_detach_driver(struct qlcnic_adapter *adapter)
	struct net_device *netdev = adapter->netdev;

	netif_device_detach(netdev);
	qlcnic_83xx_detach_mailbox_work(adapter);

	/* Disable mailbox interrupt */
	qlcnic_83xx_disable_mbx_intr(adapter);
@@ -610,6 +611,9 @@ int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter)
{
	int err;

	qlcnic_83xx_reinit_mbx_work(adapter->ahw->mailbox);
	qlcnic_83xx_enable_mbx_interrupt(adapter);

	/* register for NIC IDC AEN Events */
	qlcnic_83xx_register_nic_idc_func(adapter, 1);

@@ -617,7 +621,7 @@ int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter)
	if (err)
		return err;

	qlcnic_83xx_enable_mbx_intrpt(adapter);
	qlcnic_83xx_enable_mbx_interrupt(adapter);

	if (qlcnic_83xx_configure_opmode(adapter)) {
		qlcnic_83xx_idc_enter_failed_state(adapter, 1);
@@ -640,7 +644,6 @@ static void qlcnic_83xx_idc_update_idc_params(struct qlcnic_adapter *adapter)
	struct qlcnic_hardware_context *ahw = adapter->ahw;

	qlcnic_83xx_idc_update_drv_presence_reg(adapter, 1, 1);
	set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status);
	qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1);
	set_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status);

@@ -810,9 +813,10 @@ static int qlcnic_83xx_idc_init_state(struct qlcnic_adapter *adapter)
 **/
static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
{
	u32 val;
	struct qlcnic_hardware_context *ahw = adapter->ahw;
	struct qlcnic_mailbox *mbx = ahw->mailbox;
	int ret = 0;
	u32 val;

	/* Perform NIC configuration based ready state entry actions */
	if (ahw->idc.state_entry(adapter))
@@ -824,7 +828,7 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
			dev_err(&adapter->pdev->dev,
				"Error: device temperature %d above limits\n",
				adapter->ahw->temp);
			clear_bit(QLC_83XX_MBX_READY, &ahw->idc.status);
			clear_bit(QLC_83XX_MBX_READY, &mbx->status);
			set_bit(__QLCNIC_RESETTING, &adapter->state);
			qlcnic_83xx_idc_detach_driver(adapter);
			qlcnic_83xx_idc_enter_failed_state(adapter, 1);
@@ -837,7 +841,7 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
	if (ret) {
		adapter->flags |= QLCNIC_FW_HANG;
		if (!(val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY)) {
			clear_bit(QLC_83XX_MBX_READY, &ahw->idc.status);
			clear_bit(QLC_83XX_MBX_READY, &mbx->status);
			set_bit(__QLCNIC_RESETTING, &adapter->state);
			qlcnic_83xx_idc_enter_need_reset_state(adapter, 1);
		}
@@ -845,6 +849,8 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
	}

	if ((val & QLC_83XX_IDC_GRACEFULL_RESET) || ahw->idc.collect_dump) {
		clear_bit(QLC_83XX_MBX_READY, &mbx->status);

		/* Move to need reset state and prepare for reset */
		qlcnic_83xx_idc_enter_need_reset_state(adapter, 1);
		return ret;
@@ -882,12 +888,13 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter)
 **/
static int qlcnic_83xx_idc_need_reset_state(struct qlcnic_adapter *adapter)
{
	struct qlcnic_mailbox *mbx = adapter->ahw->mailbox;
	int ret = 0;

	if (adapter->ahw->idc.prev_state != QLC_83XX_IDC_DEV_NEED_RESET) {
		qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1);
		set_bit(__QLCNIC_RESETTING, &adapter->state);
		clear_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status);
		clear_bit(QLC_83XX_MBX_READY, &mbx->status);
		if (adapter->ahw->nic_mode == QLC_83XX_VIRTUAL_NIC_MODE)
			qlcnic_83xx_disable_vnic_mode(adapter, 1);

@@ -1079,7 +1086,6 @@ static void qlcnic_83xx_setup_idc_parameters(struct qlcnic_adapter *adapter)
	adapter->ahw->idc.name = (char **)qlc_83xx_idc_states;

	clear_bit(__QLCNIC_RESETTING, &adapter->state);
	set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status);
	set_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status);

	/* Check if reset recovery is disabled */
@@ -1190,6 +1196,9 @@ void qlcnic_83xx_idc_request_reset(struct qlcnic_adapter *adapter, u32 key)
{
	u32 val;

	if (qlcnic_sriov_vf_check(adapter))
		return;

	if (qlcnic_83xx_lock_driver(adapter)) {
		dev_err(&adapter->pdev->dev,
			"%s:failed, please retry\n", __func__);
@@ -2110,17 +2119,35 @@ static void qlcnic_83xx_clear_function_resources(struct qlcnic_adapter *adapter)
int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
{
	struct qlcnic_hardware_context *ahw = adapter->ahw;
	int err = 0;

	if (qlcnic_sriov_vf_check(adapter))
		return qlcnic_sriov_vf_init(adapter, pci_using_dac);
	ahw->msix_supported = !!qlcnic_use_msi_x;
	err = qlcnic_83xx_init_mailbox_work(adapter);
	if (err)
		goto exit;

	if (qlcnic_83xx_check_hw_status(adapter))
		return -EIO;
	if (qlcnic_sriov_vf_check(adapter)) {
		err = qlcnic_sriov_vf_init(adapter, pci_using_dac);
		if (err)
			goto detach_mbx;
		else
			return err;
	}

	/* Initilaize 83xx mailbox spinlock */
	spin_lock_init(&ahw->mbx_lock);
	err = qlcnic_83xx_check_hw_status(adapter);
	if (err)
		goto detach_mbx;

	err = qlcnic_setup_intr(adapter, 0);
	if (err) {
		dev_err(&adapter->pdev->dev, "Failed to setup interrupt\n");
		goto disable_intr;
	}

	err = qlcnic_83xx_setup_mbx_intr(adapter);
	if (err)
		goto disable_mbx_intr;

	set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status);
	qlcnic_83xx_clear_function_resources(adapter);

	/* register for NIC IDC AEN Events */
@@ -2129,21 +2156,35 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
	if (!qlcnic_83xx_read_flash_descriptor_table(adapter))
		qlcnic_83xx_read_flash_mfg_id(adapter);

	if (qlcnic_83xx_idc_init(adapter))
		return -EIO;
	err = qlcnic_83xx_idc_init(adapter);
	if (err)
		goto disable_mbx_intr;

	/* Configure default, SR-IOV or Virtual NIC mode of operation */
	if (qlcnic_83xx_configure_opmode(adapter))
		return -EIO;
	err = qlcnic_83xx_configure_opmode(adapter);
	if (err)
		goto disable_mbx_intr;

	/* Perform operating mode specific initialization */
	if (adapter->nic_ops->init_driver(adapter))
		return -EIO;
	err = adapter->nic_ops->init_driver(adapter);
	if (err)
		goto disable_mbx_intr;

	INIT_DELAYED_WORK(&adapter->idc_aen_work, qlcnic_83xx_idc_aen_work);

	/* Periodically monitor device status */
	qlcnic_83xx_idc_poll_dev_state(&adapter->fw_work.work);
	return 0;

	return adapter->ahw->idc.err_code;
disable_mbx_intr:
	qlcnic_83xx_free_mbx_intr(adapter);

disable_intr:
	qlcnic_teardown_intr(adapter);

detach_mbx:
	qlcnic_83xx_detach_mailbox_work(adapter);
	qlcnic_83xx_free_mailbox(ahw->mailbox);
exit:
	return err;
}
+3 −3
Original line number Diff line number Diff line
@@ -980,9 +980,9 @@ int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
		msleep(500);
		qlcnic_process_rcv_ring_diag(sds_ring);
		if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) {
			netdev_info(netdev, "firmware didnt respond to loopback"
				" configure request\n");
			ret = -QLCNIC_FW_NOT_RESPOND;
			netdev_info(netdev,
				    "Firmware didn't sent link up event to loopback request\n");
			ret = -ETIMEDOUT;
			goto free_res;
		} else if (adapter->ahw->diag_cnt) {
			ret = adapter->ahw->diag_cnt;
Loading