Commit 4e8acb01 authored by Rajesh Borundia's avatar Rajesh Borundia Committed by David S. Miller

qlcnic: configure port on eswitch

o Nic partition capable devices has embedded switch, this needs to support
various features like external switch.
Signed-off-by: default avatarRajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: default avatarAmit Kumar Salecha <amit.salecha@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 251b036a
......@@ -556,6 +556,7 @@ struct qlcnic_recv_context {
#define QLCNIC_CDRP_CMD_GET_ESWITCH_STATUS 0x00000026
#define QLCNIC_CDRP_CMD_SET_PORTMIRRORING 0x00000027
#define QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH 0x00000028
#define QLCNIC_CDRP_CMD_GET_ESWITCH_PORT_CONFIG 0x00000029
#define QLCNIC_CDRP_CMD_GET_ESWITCH_STATS 0x0000002a
#define QLCNIC_RCODE_SUCCESS 0
......@@ -1044,7 +1045,7 @@ struct qlcnic_pci_info {
};
struct qlcnic_npar_info {
u16 vlan_id;
u16 pvid;
u16 min_bw;
u16 max_bw;
u8 phy_port;
......@@ -1052,11 +1053,13 @@ struct qlcnic_npar_info {
u8 active;
u8 enable_pm;
u8 dest_npar;
u8 host_vlan_tag;
u8 promisc_mode;
u8 discard_tagged;
u8 mac_learning;
u8 mac_anti_spoof;
u8 promisc_mode;
u8 offload_flags;
};
struct qlcnic_eswitch {
u8 port;
u8 active_vports;
......@@ -1088,7 +1091,6 @@ struct qlcnic_eswitch {
#define IS_VALID_BW(bw) (bw >= MIN_BW && bw <= MAX_BW)
#define IS_VALID_TX_QUEUES(que) (que > 0 && que <= MAX_TX_QUEUES)
#define IS_VALID_RX_QUEUES(que) (que > 0 && que <= MAX_RX_QUEUES)
#define IS_VALID_MODE(mode) (mode == 0 || mode == 1)
struct qlcnic_pci_func_cfg {
u16 func_type;
......@@ -1120,12 +1122,16 @@ struct qlcnic_pm_func_cfg {
struct qlcnic_esw_func_cfg {
u16 vlan_id;
u8 op_mode;
u8 op_type;
u8 pci_func;
u8 host_vlan_tag;
u8 promisc_mode;
u8 discard_tagged;
u8 mac_learning;
u8 reserved;
u8 mac_anti_spoof;
u8 offload_flags;
u8 reserved[5];
};
#define QLCNIC_STATS_VERSION 1
......@@ -1276,8 +1282,10 @@ int qlcnic_get_eswitch_capabilities(struct qlcnic_adapter *, u8,
int qlcnic_get_eswitch_status(struct qlcnic_adapter *, u8,
struct qlcnic_eswitch *);
int qlcnic_toggle_eswitch(struct qlcnic_adapter *, u8, u8);
int qlcnic_config_switch_port(struct qlcnic_adapter *, u8, int, u8, u8,
u8, u8, u16);
int qlcnic_config_switch_port(struct qlcnic_adapter *,
struct qlcnic_esw_func_cfg *);
int qlcnic_get_eswitch_port_config(struct qlcnic_adapter *,
struct qlcnic_esw_func_cfg *);
int qlcnic_config_port_mirroring(struct qlcnic_adapter *, u8, u8, u8);
int qlcnic_get_port_stats(struct qlcnic_adapter *, const u8, const u8,
struct __qlcnic_esw_statistics *);
......
......@@ -813,9 +813,8 @@ int qlcnic_get_eswitch_capabilities(struct qlcnic_adapter *adapter, u8 port,
arg2 = QLCRD32(adapter, QLCNIC_ARG2_CRB_OFFSET);
eswitch->port = arg1 & 0xf;
eswitch->active_vports = LSB(arg2);
eswitch->max_ucast_filters = MSB(arg2);
eswitch->max_active_vlans = LSB(MSW(arg2));
eswitch->max_ucast_filters = LSW(arg2);
eswitch->max_active_vlans = MSW(arg2) & 0xfff;
if (arg1 & BIT_6)
eswitch->flags |= QLCNIC_SWITCH_VLAN_FILTERING;
if (arg1 & BIT_7)
......@@ -943,47 +942,6 @@ int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id,
return err;
}
/* Configure eSwitch port */
int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, u8 id,
int vlan_tagging, u8 discard_tagged, u8 promsc_mode,
u8 mac_learn, u8 pci_func, u16 vlan_id)
{
int err = -EIO;
u32 arg1;
struct qlcnic_eswitch *eswitch;
if (adapter->op_mode != QLCNIC_MGMT_FUNC)
return err;
eswitch = &adapter->eswitch[id];
if (!(eswitch->flags & QLCNIC_SWITCH_ENABLE))
return err;
arg1 = eswitch->port | (discard_tagged ? BIT_4 : 0);
arg1 |= (promsc_mode ? BIT_6 : 0) | (mac_learn ? BIT_7 : 0);
arg1 |= pci_func << 8;
if (vlan_tagging)
arg1 |= BIT_5 | (vlan_id << 16);
err = qlcnic_issue_cmd(adapter,
adapter->ahw.pci_func,
adapter->fw_hal_version,
arg1,
0,
0,
QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH);
if (err != QLCNIC_RCODE_SUCCESS) {
dev_err(&adapter->pdev->dev,
"Failed to configure eswitch port%d\n", eswitch->port);
} else {
dev_info(&adapter->pdev->dev,
"Configured eSwitch for port %d\n", eswitch->port);
}
return err;
}
int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) {
......@@ -1108,3 +1066,131 @@ int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw,
"rx_ctx=%d\n", func_esw, port, rx_tx);
return -EIO;
}
static int
__qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
u32 *arg1, u32 *arg2)
{
int err = -EIO;
u8 pci_func;
pci_func = (*arg1 >> 8);
err = qlcnic_issue_cmd(adapter,
adapter->ahw.pci_func,
adapter->fw_hal_version,
*arg1,
0,
0,
QLCNIC_CDRP_CMD_GET_ESWITCH_PORT_CONFIG);
if (err == QLCNIC_RCODE_SUCCESS) {
*arg1 = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET);
*arg2 = QLCRD32(adapter, QLCNIC_ARG2_CRB_OFFSET);
dev_info(&adapter->pdev->dev,
"eSwitch port config for pci func%d\n", pci_func);
} else {
dev_err(&adapter->pdev->dev,
"Failed to get eswitch port config%d\n", pci_func);
}
return err;
}
/* Configure eSwitch port
op_mode = 0 for setting default port behavior
op_mode = 1 for setting vlan id
op_mode = 2 for deleting vlan id
op_type = 0 for vlan_id
op_type = 1 for port vlan_id
*/
int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
struct qlcnic_esw_func_cfg *esw_cfg)
{
int err = -EIO;
u32 arg1, arg2 = 0;
u8 pci_func;
if (adapter->op_mode != QLCNIC_MGMT_FUNC)
return err;
pci_func = esw_cfg->pci_func;
arg1 = (adapter->npars[pci_func].phy_port & BIT_0);
arg1 |= (pci_func << 8);
if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2))
return err;
arg1 &= ~(0x0ff << 8);
arg1 |= (pci_func << 8);
arg1 &= ~(BIT_2 | BIT_3);
switch (esw_cfg->op_mode) {
case QLCNIC_PORT_DEFAULTS:
arg1 |= (BIT_4 | BIT_6 | BIT_7);
arg2 |= (BIT_0 | BIT_1);
if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO)
arg2 |= (BIT_2 | BIT_3);
if (!(esw_cfg->discard_tagged))
arg1 &= ~BIT_4;
if (!(esw_cfg->promisc_mode))
arg1 &= ~BIT_6;
if (!(esw_cfg->mac_learning))
arg1 &= ~BIT_7;
if (!(esw_cfg->mac_anti_spoof))
arg2 &= ~BIT_0;
if (!(esw_cfg->offload_flags & BIT_0))
arg2 &= ~(BIT_1 | BIT_2 | BIT_3);
if (!(esw_cfg->offload_flags & BIT_1))
arg2 &= ~BIT_2;
if (!(esw_cfg->offload_flags & BIT_2))
arg2 &= ~BIT_3;
break;
case QLCNIC_ADD_VLAN:
arg1 |= (BIT_2 | BIT_5);
arg1 |= (esw_cfg->vlan_id << 16);
break;
case QLCNIC_DEL_VLAN:
arg1 |= (BIT_3 | BIT_5);
arg1 &= ~(0x0ffff << 16);
default:
return err;
}
err = qlcnic_issue_cmd(adapter,
adapter->ahw.pci_func,
adapter->fw_hal_version,
arg1,
arg2,
0,
QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH);
if (err != QLCNIC_RCODE_SUCCESS) {
dev_err(&adapter->pdev->dev,
"Failed to configure eswitch port%d\n", pci_func);
} else {
dev_info(&adapter->pdev->dev,
"Configured eSwitch for port %d\n", pci_func);
}
return err;
}
int
qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
struct qlcnic_esw_func_cfg *esw_cfg)
{
u32 arg1, arg2;
u8 phy_port;
if (adapter->op_mode == QLCNIC_MGMT_FUNC)
phy_port = adapter->npars[esw_cfg->pci_func].phy_port;
else
phy_port = adapter->physical_port;
arg1 = phy_port;
arg1 |= (esw_cfg->pci_func << 8);
if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2))
return -EIO;
esw_cfg->discard_tagged = !!(arg1 & BIT_4);
esw_cfg->host_vlan_tag = !!(arg1 & BIT_5);
esw_cfg->promisc_mode = !!(arg1 & BIT_6);
esw_cfg->mac_learning = !!(arg1 & BIT_7);
esw_cfg->vlan_id = LSW(arg1 >> 16);
esw_cfg->mac_anti_spoof = (arg2 & 0x1);
esw_cfg->offload_flags = ((arg2 >> 1) & 0x7);
return 0;
}
......@@ -775,6 +775,7 @@ struct qlcnic_legacy_intr_set {
#define QLCNIC_DRV_OP_MODE 0x1b2170
#define QLCNIC_MSIX_BASE 0x132110
#define QLCNIC_MAX_PCI_FUNC 8
#define QLCNIC_MAX_VLAN_FILTERS 64
/* PCI function operational mode */
enum {
......@@ -783,6 +784,12 @@ enum {
QLCNIC_NON_PRIV_FUNC = 2
};
enum {
QLCNIC_PORT_DEFAULTS = 0,
QLCNIC_ADD_VLAN = 1,
QLCNIC_DEL_VLAN = 2
};
#define QLC_DEV_DRV_DEFAULT 0x11111111
#define LSB(x) ((uint8_t)(x))
......
This diff is collapsed.
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