Skip to content

Commit

Permalink
qed: Add link support
Browse files Browse the repository at this point in the history
Physical link is handled by the management Firmware.
This patch lays the infrastructure for attention handling in the driver,
as link change notifications arrive via async. attentions,
as well the handling of such notifications.

This patch also extends the API with the protocol drivers by adding
registered callbacks which the protocol driver passes to qed in order
to be notified of async. events originating from the FW/HW.

Signed-off-by: Yuval Mintz <[email protected]>
Signed-off-by: Ariel Elior <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Yuval Mintz authored and davem330 committed Oct 28, 2015
1 parent 0d8e0aa commit cc875c2
Show file tree
Hide file tree
Showing 8 changed files with 1,102 additions and 5 deletions.
20 changes: 20 additions & 0 deletions drivers/net/ethernet/qlogic/qed/qed.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,18 @@ enum QED_FEATURE {
QED_MAX_FEATURES,
};

enum QED_PORT_MODE {
QED_PORT_MODE_DE_2X40G,
QED_PORT_MODE_DE_2X50G,
QED_PORT_MODE_DE_1X100G,
QED_PORT_MODE_DE_4X10G_F,
QED_PORT_MODE_DE_4X10G_E,
QED_PORT_MODE_DE_4X20G,
QED_PORT_MODE_DE_1X40G,
QED_PORT_MODE_DE_2X25G,
QED_PORT_MODE_DE_1X25G
};

struct qed_hw_info {
/* PCI personality */
enum qed_pci_personality personality;
Expand Down Expand Up @@ -404,6 +416,13 @@ struct qed_dev {
u8 protocol;
#define IS_QED_ETH_IF(cdev) ((cdev)->protocol == QED_PROTOCOL_ETH)

/* Callbacks to protocol driver */
union {
struct qed_common_cb_ops *common;
struct qed_eth_cb_ops *eth;
} protocol_ops;
void *ops_cookie;

const struct firmware *firmware;
};

Expand Down Expand Up @@ -453,6 +472,7 @@ static inline u8 qed_concrete_to_sw_fid(struct qed_dev *cdev,
/* Prototypes */
int qed_fill_dev_info(struct qed_dev *cdev,
struct qed_dev_info *dev_info);
void qed_link_update(struct qed_hwfn *hwfn);
u32 qed_unzip_data(struct qed_hwfn *p_hwfn,
u32 input_len, u8 *input_buf,
u32 max_size, u8 *unzip_buf);
Expand Down
106 changes: 104 additions & 2 deletions drivers/net/ethernet/qlogic/qed/qed_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -1039,8 +1039,9 @@ static void qed_hw_get_resc(struct qed_hwfn *p_hwfn)
static int qed_hw_get_nvm_info(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt)
{
u32 nvm_cfg1_offset, mf_mode, addr, generic_cont0, nvm_cfg_addr;
u32 val;
u32 nvm_cfg1_offset, mf_mode, addr, generic_cont0, core_cfg;
u32 port_cfg_addr, link_temp, val, nvm_cfg_addr;
struct qed_mcp_link_params *link;

/* Read global nvm_cfg address */
nvm_cfg_addr = qed_rd(p_hwfn, p_ptt, MISC_REG_GEN_PURP_CR0);
Expand All @@ -1060,6 +1061,48 @@ static int qed_hw_get_nvm_info(struct qed_hwfn *p_hwfn,
offsetof(struct nvm_cfg1_glob, pci_id);
p_hwfn->hw_info.vendor_id = qed_rd(p_hwfn, p_ptt, addr) &
NVM_CFG1_GLOB_VENDOR_ID_MASK;

addr = MCP_REG_SCRATCH + nvm_cfg1_offset +
offsetof(struct nvm_cfg1, glob) +
offsetof(struct nvm_cfg1_glob, core_cfg);

core_cfg = qed_rd(p_hwfn, p_ptt, addr);

switch ((core_cfg & NVM_CFG1_GLOB_NETWORK_PORT_MODE_MASK) >>
NVM_CFG1_GLOB_NETWORK_PORT_MODE_OFFSET) {
case NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_2X40G:
p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_2X40G;
break;
case NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_2X50G:
p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_2X50G;
break;
case NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_1X100G:
p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_1X100G;
break;
case NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_4X10G_F:
p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_4X10G_F;
break;
case NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_4X10G_E:
p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_4X10G_E;
break;
case NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_4X20G:
p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_4X20G;
break;
case NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_1X40G:
p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_1X40G;
break;
case NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_2X25G:
p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_2X25G;
break;
case NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_1X25G:
p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_1X25G;
break;
default:
DP_NOTICE(p_hwfn, "Unknown port mode in 0x%08x\n",
core_cfg);
break;
}

addr = MCP_REG_SCRATCH + nvm_cfg1_offset +
offsetof(struct nvm_cfg1, func[MCP_PF_ID(p_hwfn)]) +
offsetof(struct nvm_cfg1_func, device_id);
Expand All @@ -1075,6 +1118,65 @@ static int qed_hw_get_nvm_info(struct qed_hwfn *p_hwfn,
NVM_CFG1_FUNC_VENDOR_DEVICE_ID_OFFSET;
}

/* Read default link configuration */
link = &p_hwfn->mcp_info->link_input;
port_cfg_addr = MCP_REG_SCRATCH + nvm_cfg1_offset +
offsetof(struct nvm_cfg1, port[MFW_PORT(p_hwfn)]);
link_temp = qed_rd(p_hwfn, p_ptt,
port_cfg_addr +
offsetof(struct nvm_cfg1_port, speed_cap_mask));
link->speed.advertised_speeds =
link_temp & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_MASK;

p_hwfn->mcp_info->link_capabilities.speed_capabilities =
link->speed.advertised_speeds;

link_temp = qed_rd(p_hwfn, p_ptt,
port_cfg_addr +
offsetof(struct nvm_cfg1_port, link_settings));
switch ((link_temp & NVM_CFG1_PORT_DRV_LINK_SPEED_MASK) >>
NVM_CFG1_PORT_DRV_LINK_SPEED_OFFSET) {
case NVM_CFG1_PORT_DRV_LINK_SPEED_AUTONEG:
link->speed.autoneg = true;
break;
case NVM_CFG1_PORT_DRV_LINK_SPEED_1G:
link->speed.forced_speed = 1000;
break;
case NVM_CFG1_PORT_DRV_LINK_SPEED_10G:
link->speed.forced_speed = 10000;
break;
case NVM_CFG1_PORT_DRV_LINK_SPEED_25G:
link->speed.forced_speed = 25000;
break;
case NVM_CFG1_PORT_DRV_LINK_SPEED_40G:
link->speed.forced_speed = 40000;
break;
case NVM_CFG1_PORT_DRV_LINK_SPEED_50G:
link->speed.forced_speed = 50000;
break;
case NVM_CFG1_PORT_DRV_LINK_SPEED_100G:
link->speed.forced_speed = 100000;
break;
default:
DP_NOTICE(p_hwfn, "Unknown Speed in 0x%08x\n",
link_temp);
}

link_temp &= NVM_CFG1_PORT_DRV_FLOW_CONTROL_MASK;
link_temp >>= NVM_CFG1_PORT_DRV_FLOW_CONTROL_OFFSET;
link->pause.autoneg = !!(link_temp &
NVM_CFG1_PORT_DRV_FLOW_CONTROL_AUTONEG);
link->pause.forced_rx = !!(link_temp &
NVM_CFG1_PORT_DRV_FLOW_CONTROL_RX);
link->pause.forced_tx = !!(link_temp &
NVM_CFG1_PORT_DRV_FLOW_CONTROL_TX);
link->loopback_mode = 0;

DP_VERBOSE(p_hwfn, NETIF_MSG_LINK,
"Read default link: Speed 0x%08x, Adv. Speed 0x%08x, AN: 0x%02x, PAUSE AN: 0x%02x\n",
link->speed.forced_speed, link->speed.advertised_speeds,
link->speed.autoneg, link->pause.autoneg);

/* Read Multi-function information from shmem */
addr = MCP_REG_SCRATCH + nvm_cfg1_offset +
offsetof(struct nvm_cfg1, glob) +
Expand Down
Loading

0 comments on commit cc875c2

Please sign in to comment.