Commit 7cb03b23 authored by Rajesh Borundia's avatar Rajesh Borundia Committed by David S. Miller

qlcnic: Support VF-PF communication channel commands.

o Add support for commands from VF to PF.
o PF validates the commands sent by the VF before sending
  it to adapter.
o vPort is a container of resources. PF creates vPort
  for VFs and attach resources to it. vPort is
  transparent to the VF.
o Separate 83xx TX and RX hardware resource cleanup from 82xx.
Signed-off-by: default avatarManish Chopra <manish.chopra@qlogic.com>
Signed-off-by: default avatarSucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: default avatarRajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f197a7aa
......@@ -1584,6 +1584,9 @@ struct qlcnic_hardware_ops {
int (*create_rx_ctx) (struct qlcnic_adapter *);
int (*create_tx_ctx) (struct qlcnic_adapter *,
struct qlcnic_host_tx_ring *, int);
void (*del_rx_ctx) (struct qlcnic_adapter *);
void (*del_tx_ctx) (struct qlcnic_adapter *,
struct qlcnic_host_tx_ring *);
int (*setup_link_event) (struct qlcnic_adapter *, int);
int (*get_nic_info) (struct qlcnic_adapter *, struct qlcnic_info *, u8);
int (*get_pci_info) (struct qlcnic_adapter *, struct qlcnic_pci_info *);
......@@ -1703,6 +1706,17 @@ static inline int qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter,
return adapter->ahw->hw_ops->create_tx_ctx(adapter, ptr, ring);
}
static inline void qlcnic_fw_cmd_del_rx_ctx(struct qlcnic_adapter *adapter)
{
return adapter->ahw->hw_ops->del_rx_ctx(adapter);
}
static inline void qlcnic_fw_cmd_del_tx_ctx(struct qlcnic_adapter *adapter,
struct qlcnic_host_tx_ring *ptr)
{
return adapter->ahw->hw_ops->del_tx_ctx(adapter, ptr);
}
static inline int qlcnic_linkevent_request(struct qlcnic_adapter *adapter,
int enable)
{
......
......@@ -88,6 +88,153 @@
#define QLC_83XX_MAX_RESET_SEQ_ENTRIES 16
/* status descriptor mailbox data
* @phy_addr_{low|high}: physical address of buffer
* @sds_ring_size: buffer size
* @intrpt_id: interrupt id
* @intrpt_val: source of interrupt
*/
struct qlcnic_sds_mbx {
u32 phy_addr_low;
u32 phy_addr_high;
u32 rsvd1[4];
#if defined(__LITTLE_ENDIAN)
u16 sds_ring_size;
u16 rsvd2;
u16 rsvd3[2];
u16 intrpt_id;
u8 intrpt_val;
u8 rsvd4;
#elif defined(__BIG_ENDIAN)
u16 rsvd2;
u16 sds_ring_size;
u16 rsvd3[2];
u8 rsvd4;
u8 intrpt_val;
u16 intrpt_id;
#endif
u32 rsvd5;
} __packed;
/* receive descriptor buffer data
* phy_addr_reg_{low|high}: physical address of regular buffer
* phy_addr_jmb_{low|high}: physical address of jumbo buffer
* reg_ring_sz: size of regular buffer
* reg_ring_len: no. of entries in regular buffer
* jmb_ring_len: no. of entries in jumbo buffer
* jmb_ring_sz: size of jumbo buffer
*/
struct qlcnic_rds_mbx {
u32 phy_addr_reg_low;
u32 phy_addr_reg_high;
u32 phy_addr_jmb_low;
u32 phy_addr_jmb_high;
#if defined(__LITTLE_ENDIAN)
u16 reg_ring_sz;
u16 reg_ring_len;
u16 jmb_ring_sz;
u16 jmb_ring_len;
#elif defined(__BIG_ENDIAN)
u16 reg_ring_len;
u16 reg_ring_sz;
u16 jmb_ring_len;
u16 jmb_ring_sz;
#endif
} __packed;
/* host producers for regular and jumbo rings */
struct __host_producer_mbx {
u32 reg_buf;
u32 jmb_buf;
} __packed;
/* Receive context mailbox data outbox registers
* @state: state of the context
* @vport_id: virtual port id
* @context_id: receive context id
* @num_pci_func: number of pci functions of the port
* @phy_port: physical port id
*/
struct qlcnic_rcv_mbx_out {
#if defined(__LITTLE_ENDIAN)
u8 rcv_num;
u8 sts_num;
u16 ctx_id;
u8 state;
u8 num_pci_func;
u8 phy_port;
u8 vport_id;
#elif defined(__BIG_ENDIAN)
u16 ctx_id;
u8 sts_num;
u8 rcv_num;
u8 vport_id;
u8 phy_port;
u8 num_pci_func;
u8 state;
#endif
u32 host_csmr[QLCNIC_MAX_RING_SETS];
struct __host_producer_mbx host_prod[QLCNIC_MAX_RING_SETS];
} __packed;
struct qlcnic_add_rings_mbx_out {
#if defined(__LITTLE_ENDIAN)
u8 rcv_num;
u8 sts_num;
u16 ctx_id;
#elif defined(__BIG_ENDIAN)
u16 ctx_id;
u8 sts_num;
u8 rcv_num;
#endif
u32 host_csmr[QLCNIC_MAX_RING_SETS];
struct __host_producer_mbx host_prod[QLCNIC_MAX_RING_SETS];
} __packed;
/* Transmit context mailbox inbox registers
* @phys_addr_{low|high}: DMA address of the transmit buffer
* @cnsmr_index_{low|high}: host consumer index
* @size: legth of transmit buffer ring
* @intr_id: interrput id
* @src: src of interrupt
*/
struct qlcnic_tx_mbx {
u32 phys_addr_low;
u32 phys_addr_high;
u32 cnsmr_index_low;
u32 cnsmr_index_high;
#if defined(__LITTLE_ENDIAN)
u16 size;
u16 intr_id;
u8 src;
u8 rsvd[3];
#elif defined(__BIG_ENDIAN)
u16 intr_id;
u16 size;
u8 rsvd[3];
u8 src;
#endif
} __packed;
/* Transmit context mailbox outbox registers
* @host_prod: host producer index
* @ctx_id: transmit context id
* @state: state of the transmit context
*/
struct qlcnic_tx_mbx_out {
u32 host_prod;
#if defined(__LITTLE_ENDIAN)
u16 ctx_id;
u8 state;
u8 rsvd;
#elif defined(__BIG_ENDIAN)
u8 rsvd;
u8 state;
u16 ctx_id;
#endif
} __packed;
struct qlcnic_intrpt_config {
u8 type;
u8 enabled;
......@@ -369,6 +516,9 @@ int qlcnic_ind_rd(struct qlcnic_adapter *, u32);
int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *);
int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *,
struct qlcnic_host_tx_ring *, int);
void qlcnic_83xx_del_rx_ctx(struct qlcnic_adapter *);
void qlcnic_83xx_del_tx_ctx(struct qlcnic_adapter *,
struct qlcnic_host_tx_ring *);
int qlcnic_83xx_get_nic_info(struct qlcnic_adapter *, struct qlcnic_info *, u8);
int qlcnic_83xx_setup_link_event(struct qlcnic_adapter *, int);
void qlcnic_83xx_process_rcv_ring_diag(struct qlcnic_host_sds_ring *);
......
......@@ -382,8 +382,7 @@ int qlcnic_82xx_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
return err;
}
static void
qlcnic_fw_cmd_destroy_rx_ctx(struct qlcnic_adapter *adapter)
void qlcnic_82xx_fw_cmd_del_rx_ctx(struct qlcnic_adapter *adapter)
{
int err;
struct qlcnic_cmd_args cmd;
......@@ -484,13 +483,13 @@ int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter,
return err;
}
static void
qlcnic_fw_cmd_destroy_tx_ctx(struct qlcnic_adapter *adapter,
struct qlcnic_host_tx_ring *tx_ring)
void qlcnic_82xx_fw_cmd_del_tx_ctx(struct qlcnic_adapter *adapter,
struct qlcnic_host_tx_ring *tx_ring)
{
struct qlcnic_cmd_args cmd;
qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DESTROY_TX_CTX);
cmd.req.arg[1] = tx_ring->ctx_id;
if (qlcnic_issue_cmd(adapter, &cmd))
dev_err(&adapter->pdev->dev,
......@@ -605,13 +604,12 @@ int qlcnic_fw_create_ctx(struct qlcnic_adapter *dev)
&dev->tx_ring[ring],
ring);
if (err) {
qlcnic_fw_cmd_destroy_rx_ctx(dev);
qlcnic_fw_cmd_del_rx_ctx(dev);
if (ring == 0)
goto err_out;
for (i = 0; i < ring; i++)
qlcnic_fw_cmd_destroy_tx_ctx(dev,
&dev->tx_ring[i]);
qlcnic_fw_cmd_del_tx_ctx(dev, &dev->tx_ring[i]);
goto err_out;
}
......@@ -633,10 +631,10 @@ void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter)
int ring;
if (test_and_clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) {
qlcnic_fw_cmd_destroy_rx_ctx(adapter);
qlcnic_fw_cmd_del_rx_ctx(adapter);
for (ring = 0; ring < adapter->max_drv_tx_rings; ring++)
qlcnic_fw_cmd_destroy_tx_ctx(adapter,
&adapter->tx_ring[ring]);
qlcnic_fw_cmd_del_tx_ctx(adapter,
&adapter->tx_ring[ring]);
if (qlcnic_83xx_check(adapter) &&
(adapter->flags & QLCNIC_MSIX_ENABLED)) {
......
......@@ -178,6 +178,9 @@ int qlcnic_82xx_issue_cmd(struct qlcnic_adapter *adapter,
int qlcnic_82xx_fw_cmd_create_rx_ctx(struct qlcnic_adapter *);
int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *,
struct qlcnic_host_tx_ring *tx_ring, int);
void qlcnic_82xx_fw_cmd_del_rx_ctx(struct qlcnic_adapter *);
void qlcnic_82xx_fw_cmd_del_tx_ctx(struct qlcnic_adapter *,
struct qlcnic_host_tx_ring *);
int qlcnic_82xx_sre_macaddr_change(struct qlcnic_adapter *, u8 *, __le16, u8);
int qlcnic_82xx_get_mac_address(struct qlcnic_adapter *, u8*);
int qlcnic_82xx_get_nic_info(struct qlcnic_adapter *, struct qlcnic_info *, u8);
......
......@@ -147,7 +147,10 @@ static inline u8 qlcnic_mac_hash(u64 mac)
static inline u32 qlcnic_get_ref_handle(struct qlcnic_adapter *adapter,
u16 handle, u8 ring_id)
{
if (adapter->pdev->device == PCI_DEVICE_ID_QLOGIC_QLE834X)
unsigned short device = adapter->pdev->device;
if ((device == PCI_DEVICE_ID_QLOGIC_QLE834X) ||
(device == PCI_DEVICE_ID_QLOGIC_VF_QLE834X))
return handle | (ring_id << 15);
else
return handle;
......
......@@ -226,6 +226,9 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p)
struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct sockaddr *addr = p;
if (qlcnic_sriov_vf_check(adapter))
return -EINVAL;
if ((adapter->flags & QLCNIC_MAC_OVERRIDE_DISABLED))
return -EOPNOTSUPP;
......@@ -379,6 +382,8 @@ static struct qlcnic_hardware_ops qlcnic_hw_ops = {
.process_lb_rcv_ring_diag = qlcnic_82xx_process_rcv_ring_diag,
.create_rx_ctx = qlcnic_82xx_fw_cmd_create_rx_ctx,
.create_tx_ctx = qlcnic_82xx_fw_cmd_create_tx_ctx,
.del_rx_ctx = qlcnic_82xx_fw_cmd_del_rx_ctx,
.del_tx_ctx = qlcnic_82xx_fw_cmd_del_tx_ctx,
.setup_link_event = qlcnic_82xx_linkevent_request,
.get_nic_info = qlcnic_82xx_get_nic_info,
.get_pci_info = qlcnic_82xx_get_pci_info,
......
......@@ -119,6 +119,8 @@ struct qlcnic_vport {
struct qlcnic_vf_info {
u8 pci_func;
u16 rx_ctx_id;
u16 tx_ctx_id;
unsigned long state;
struct completion ch_free_cmpl;
struct work_struct trans_work;
......@@ -167,9 +169,37 @@ void qlcnic_sriov_pf_process_bc_cmd(struct qlcnic_adapter *,
void qlcnic_sriov_pf_disable(struct qlcnic_adapter *);
void qlcnic_sriov_pf_cleanup(struct qlcnic_adapter *);
int qlcnic_pci_sriov_configure(struct pci_dev *, int);
void qlcnic_pf_set_interface_id_create_rx_ctx(struct qlcnic_adapter *, u32 *);
void qlcnic_pf_set_interface_id_create_tx_ctx(struct qlcnic_adapter *, u32 *);
void qlcnic_pf_set_interface_id_del_rx_ctx(struct qlcnic_adapter *, u32 *);
void qlcnic_pf_set_interface_id_del_tx_ctx(struct qlcnic_adapter *, u32 *);
void qlcnic_pf_set_interface_id_promisc(struct qlcnic_adapter *, u32 *);
void qlcnic_pf_set_interface_id_ipaddr(struct qlcnic_adapter *, u32 *);
void qlcnic_pf_set_interface_id_macaddr(struct qlcnic_adapter *, u32 *);
#else
static inline void qlcnic_sriov_pf_disable(struct qlcnic_adapter *adapter) {}
static inline void qlcnic_sriov_pf_cleanup(struct qlcnic_adapter *adapter) {}
static inline void
qlcnic_pf_set_interface_id_create_rx_ctx(struct qlcnic_adapter *adapter,
u32 *int_id) {}
static inline void
qlcnic_pf_set_interface_id_create_tx_ctx(struct qlcnic_adapter *adapter,
u32 *int_id) {}
static inline void
qlcnic_pf_set_interface_id_del_rx_ctx(struct qlcnic_adapter *adapter,
u32 *int_id) {}
static inline void
qlcnic_pf_set_interface_id_del_tx_ctx(struct qlcnic_adapter *adapter,
u32 *int_id) {}
static inline void
qlcnic_pf_set_interface_id_ipaddr(struct qlcnic_adapter *adapter, u32 *int_id)
{}
static inline void
qlcnic_pf_set_interface_id_macaddr(struct qlcnic_adapter *adapter, u32 *int_id)
{}
static inline void
qlcnic_pf_set_interface_id_promisc(struct qlcnic_adapter *adapter, u32 *int_id)
{}
#endif
#endif
......@@ -21,6 +21,9 @@
#define QLC_BC_HDR_SZ 16
#define QLC_BC_PAYLOAD_SZ (1024 - QLC_BC_HDR_SZ)
#define QLC_DEFAULT_RCV_DESCRIPTORS_SRIOV_VF 2048
#define QLC_DEFAULT_JUMBO_RCV_DESCRIPTORS_SRIOV_VF 512
static int qlcnic_sriov_vf_mbx_op(struct qlcnic_adapter *,
struct qlcnic_cmd_args *);
......@@ -39,6 +42,8 @@ static struct qlcnic_hardware_ops qlcnic_sriov_vf_hw_ops = {
.process_lb_rcv_ring_diag = qlcnic_83xx_process_rcv_ring_diag,
.create_rx_ctx = qlcnic_83xx_create_rx_ctx,
.create_tx_ctx = qlcnic_83xx_create_tx_ctx,
.del_rx_ctx = qlcnic_83xx_del_rx_ctx,
.del_tx_ctx = qlcnic_83xx_del_tx_ctx,
.setup_link_event = qlcnic_83xx_setup_link_event,
.get_nic_info = qlcnic_83xx_get_nic_info,
.get_pci_info = qlcnic_83xx_get_pci_info,
......@@ -305,6 +310,42 @@ static int qlcnic_sriov_post_bc_msg(struct qlcnic_adapter *adapter, u32 *hdr,
return rsp;
}
static void qlcnic_sriov_vf_cfg_buff_desc(struct qlcnic_adapter *adapter)
{
adapter->num_rxd = QLC_DEFAULT_RCV_DESCRIPTORS_SRIOV_VF;
adapter->max_rxd = MAX_RCV_DESCRIPTORS_10G;
adapter->num_jumbo_rxd = QLC_DEFAULT_JUMBO_RCV_DESCRIPTORS_SRIOV_VF;
adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;
adapter->num_txd = MAX_CMD_DESCRIPTORS;
adapter->max_rds_rings = MAX_RDS_RINGS;
}
static int qlcnic_sriov_vf_init_driver(struct qlcnic_adapter *adapter)
{
struct qlcnic_info nic_info;
struct qlcnic_hardware_context *ahw = adapter->ahw;
int err;
err = qlcnic_get_nic_info(adapter, &nic_info, ahw->pci_func);
if (err)
return -EIO;
if (qlcnic_83xx_get_port_info(adapter))
return -EIO;
qlcnic_sriov_vf_cfg_buff_desc(adapter);
adapter->flags |= QLCNIC_ADAPTER_INITIALIZED;
dev_info(&adapter->pdev->dev, "HAL Version: %d\n",
adapter->ahw->fw_hal_version);
ahw->physical_port = (u8) nic_info.phys_port;
ahw->switch_mode = nic_info.switch_mode;
ahw->max_mtu = nic_info.max_mtu;
ahw->op_mode = nic_info.op_mode;
ahw->capabilities = nic_info.capabilities;
return 0;
}
static int qlcnic_sriov_setup_vf(struct qlcnic_adapter *adapter,
int pci_using_dac)
{
......@@ -336,6 +377,10 @@ static int qlcnic_sriov_setup_vf(struct qlcnic_adapter *adapter,
if (err)
goto err_out_disable_bc_intr;
err = qlcnic_sriov_vf_init_driver(adapter);
if (err)
goto err_out_send_channel_term;
err = qlcnic_setup_netdev(adapter, adapter->netdev, pci_using_dac);
if (err)
goto err_out_send_channel_term;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment