mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-19 02:04:19 +08:00
Merge branch 'bnxt_en-next'
Michael Chan says: ==================== bnxt_en: updates for net-next. Non-critical bug fixes, improvements, a new ethtool feature, and a new device ID. v2: Fixed a bug in bnxt_get_module_eeprom() found by Ben Hutchings. Ajit Khaparde (2): bnxt_en: Add Support for ETHTOOL_GMODULEINFO and ETHTOOL_GMODULEEEPRO bnxt_en: Report PCIe link speed and width during driver load Michael Chan (6): bnxt_en: Reduce maximum ring pages if page size is 64K. bnxt_en: Improve the delay logic for firmware response. bnxt_en: Fix length value in dmesg log firmware error message. bnxt_en: Simplify and improve unsupported SFP+ module reporting. bnxt_en: Add BCM57314 device ID. bnxt_en: Use dma_rmb() instead of rmb(). Satish Baddipadige (1): bnxt_en: Fix invalid max channel parameter in ethtool -l. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
bf14e9ec80
@ -78,6 +78,7 @@ enum board_idx {
|
|||||||
BCM57402,
|
BCM57402,
|
||||||
BCM57404,
|
BCM57404,
|
||||||
BCM57406,
|
BCM57406,
|
||||||
|
BCM57314,
|
||||||
BCM57304_VF,
|
BCM57304_VF,
|
||||||
BCM57404_VF,
|
BCM57404_VF,
|
||||||
};
|
};
|
||||||
@ -92,6 +93,7 @@ static const struct {
|
|||||||
{ "Broadcom BCM57402 NetXtreme-E Dual-port 10Gb Ethernet" },
|
{ "Broadcom BCM57402 NetXtreme-E Dual-port 10Gb Ethernet" },
|
||||||
{ "Broadcom BCM57404 NetXtreme-E Dual-port 10Gb/25Gb Ethernet" },
|
{ "Broadcom BCM57404 NetXtreme-E Dual-port 10Gb/25Gb Ethernet" },
|
||||||
{ "Broadcom BCM57406 NetXtreme-E Dual-port 10GBase-T Ethernet" },
|
{ "Broadcom BCM57406 NetXtreme-E Dual-port 10GBase-T Ethernet" },
|
||||||
|
{ "Broadcom BCM57314 NetXtreme-C Dual-port 10Gb/25Gb/40Gb/50Gb Ethernet" },
|
||||||
{ "Broadcom BCM57304 NetXtreme-C Ethernet Virtual Function" },
|
{ "Broadcom BCM57304 NetXtreme-C Ethernet Virtual Function" },
|
||||||
{ "Broadcom BCM57404 NetXtreme-E Ethernet Virtual Function" },
|
{ "Broadcom BCM57404 NetXtreme-E Ethernet Virtual Function" },
|
||||||
};
|
};
|
||||||
@ -103,6 +105,7 @@ static const struct pci_device_id bnxt_pci_tbl[] = {
|
|||||||
{ PCI_VDEVICE(BROADCOM, 0x16d0), .driver_data = BCM57402 },
|
{ PCI_VDEVICE(BROADCOM, 0x16d0), .driver_data = BCM57402 },
|
||||||
{ PCI_VDEVICE(BROADCOM, 0x16d1), .driver_data = BCM57404 },
|
{ PCI_VDEVICE(BROADCOM, 0x16d1), .driver_data = BCM57404 },
|
||||||
{ PCI_VDEVICE(BROADCOM, 0x16d2), .driver_data = BCM57406 },
|
{ PCI_VDEVICE(BROADCOM, 0x16d2), .driver_data = BCM57406 },
|
||||||
|
{ PCI_VDEVICE(BROADCOM, 0x16df), .driver_data = BCM57314 },
|
||||||
#ifdef CONFIG_BNXT_SRIOV
|
#ifdef CONFIG_BNXT_SRIOV
|
||||||
{ PCI_VDEVICE(BROADCOM, 0x16cb), .driver_data = BCM57304_VF },
|
{ PCI_VDEVICE(BROADCOM, 0x16cb), .driver_data = BCM57304_VF },
|
||||||
{ PCI_VDEVICE(BROADCOM, 0x16d3), .driver_data = BCM57404_VF },
|
{ PCI_VDEVICE(BROADCOM, 0x16d3), .driver_data = BCM57404_VF },
|
||||||
@ -1324,15 +1327,6 @@ next_rx_no_prod:
|
|||||||
((data) & \
|
((data) & \
|
||||||
HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_PORT_ID_MASK)
|
HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_PORT_ID_MASK)
|
||||||
|
|
||||||
#define BNXT_EVENT_POLICY_MASK \
|
|
||||||
HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_MASK
|
|
||||||
|
|
||||||
#define BNXT_EVENT_POLICY_SFT \
|
|
||||||
HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_SFT
|
|
||||||
|
|
||||||
#define BNXT_GET_EVENT_POLICY(data) \
|
|
||||||
(((data) & BNXT_EVENT_POLICY_MASK) >> BNXT_EVENT_POLICY_SFT)
|
|
||||||
|
|
||||||
static int bnxt_async_event_process(struct bnxt *bp,
|
static int bnxt_async_event_process(struct bnxt *bp,
|
||||||
struct hwrm_async_event_cmpl *cmpl)
|
struct hwrm_async_event_cmpl *cmpl)
|
||||||
{
|
{
|
||||||
@ -1371,9 +1365,6 @@ static int bnxt_async_event_process(struct bnxt *bp,
|
|||||||
if (bp->pf.port_id != port_id)
|
if (bp->pf.port_id != port_id)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
bp->link_info.last_port_module_event =
|
|
||||||
BNXT_GET_EVENT_POLICY(data1);
|
|
||||||
|
|
||||||
set_bit(BNXT_HWRM_PORT_MODULE_SP_EVENT, &bp->sp_event);
|
set_bit(BNXT_HWRM_PORT_MODULE_SP_EVENT, &bp->sp_event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1503,7 +1494,7 @@ static int bnxt_poll_work(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
|
|||||||
/* The valid test of the entry must be done first before
|
/* The valid test of the entry must be done first before
|
||||||
* reading any further.
|
* reading any further.
|
||||||
*/
|
*/
|
||||||
rmb();
|
dma_rmb();
|
||||||
if (TX_CMP_TYPE(txcmp) == CMP_TYPE_TX_L2_CMP) {
|
if (TX_CMP_TYPE(txcmp) == CMP_TYPE_TX_L2_CMP) {
|
||||||
tx_pkts++;
|
tx_pkts++;
|
||||||
/* return full budget so NAPI will complete. */
|
/* return full budget so NAPI will complete. */
|
||||||
@ -2780,7 +2771,7 @@ void bnxt_hwrm_cmd_hdr_init(struct bnxt *bp, void *request, u16 req_type,
|
|||||||
static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len,
|
static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len,
|
||||||
int timeout, bool silent)
|
int timeout, bool silent)
|
||||||
{
|
{
|
||||||
int i, intr_process, rc;
|
int i, intr_process, rc, tmo_count;
|
||||||
struct input *req = msg;
|
struct input *req = msg;
|
||||||
u32 *data = msg;
|
u32 *data = msg;
|
||||||
__le32 *resp_len, *valid;
|
__le32 *resp_len, *valid;
|
||||||
@ -2809,11 +2800,12 @@ static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len,
|
|||||||
timeout = DFLT_HWRM_CMD_TIMEOUT;
|
timeout = DFLT_HWRM_CMD_TIMEOUT;
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
|
tmo_count = timeout * 40;
|
||||||
if (intr_process) {
|
if (intr_process) {
|
||||||
/* Wait until hwrm response cmpl interrupt is processed */
|
/* Wait until hwrm response cmpl interrupt is processed */
|
||||||
while (bp->hwrm_intr_seq_id != HWRM_SEQ_ID_INVALID &&
|
while (bp->hwrm_intr_seq_id != HWRM_SEQ_ID_INVALID &&
|
||||||
i++ < timeout) {
|
i++ < tmo_count) {
|
||||||
usleep_range(600, 800);
|
usleep_range(25, 40);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bp->hwrm_intr_seq_id != HWRM_SEQ_ID_INVALID) {
|
if (bp->hwrm_intr_seq_id != HWRM_SEQ_ID_INVALID) {
|
||||||
@ -2824,30 +2816,30 @@ static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len,
|
|||||||
} else {
|
} else {
|
||||||
/* Check if response len is updated */
|
/* Check if response len is updated */
|
||||||
resp_len = bp->hwrm_cmd_resp_addr + HWRM_RESP_LEN_OFFSET;
|
resp_len = bp->hwrm_cmd_resp_addr + HWRM_RESP_LEN_OFFSET;
|
||||||
for (i = 0; i < timeout; i++) {
|
for (i = 0; i < tmo_count; i++) {
|
||||||
len = (le32_to_cpu(*resp_len) & HWRM_RESP_LEN_MASK) >>
|
len = (le32_to_cpu(*resp_len) & HWRM_RESP_LEN_MASK) >>
|
||||||
HWRM_RESP_LEN_SFT;
|
HWRM_RESP_LEN_SFT;
|
||||||
if (len)
|
if (len)
|
||||||
break;
|
break;
|
||||||
usleep_range(600, 800);
|
usleep_range(25, 40);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i >= timeout) {
|
if (i >= tmo_count) {
|
||||||
netdev_err(bp->dev, "Error (timeout: %d) msg {0x%x 0x%x} len:%d\n",
|
netdev_err(bp->dev, "Error (timeout: %d) msg {0x%x 0x%x} len:%d\n",
|
||||||
timeout, le16_to_cpu(req->req_type),
|
timeout, le16_to_cpu(req->req_type),
|
||||||
le16_to_cpu(req->seq_id), *resp_len);
|
le16_to_cpu(req->seq_id), len);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Last word of resp contains valid bit */
|
/* Last word of resp contains valid bit */
|
||||||
valid = bp->hwrm_cmd_resp_addr + len - 4;
|
valid = bp->hwrm_cmd_resp_addr + len - 4;
|
||||||
for (i = 0; i < timeout; i++) {
|
for (i = 0; i < 5; i++) {
|
||||||
if (le32_to_cpu(*valid) & HWRM_RESP_VALID_MASK)
|
if (le32_to_cpu(*valid) & HWRM_RESP_VALID_MASK)
|
||||||
break;
|
break;
|
||||||
usleep_range(600, 800);
|
udelay(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i >= timeout) {
|
if (i >= 5) {
|
||||||
netdev_err(bp->dev, "Error (timeout: %d) msg {0x%x 0x%x} len:%d v:%d\n",
|
netdev_err(bp->dev, "Error (timeout: %d) msg {0x%x 0x%x} len:%d v:%d\n",
|
||||||
timeout, le16_to_cpu(req->req_type),
|
timeout, le16_to_cpu(req->req_type),
|
||||||
le16_to_cpu(req->seq_id), len, *valid);
|
le16_to_cpu(req->seq_id), len, *valid);
|
||||||
@ -4734,6 +4726,7 @@ static int bnxt_update_link(struct bnxt *bp, bool chng_link_state)
|
|||||||
link_info->transceiver = resp->xcvr_pkg_type;
|
link_info->transceiver = resp->xcvr_pkg_type;
|
||||||
link_info->phy_addr = resp->eee_config_phy_addr &
|
link_info->phy_addr = resp->eee_config_phy_addr &
|
||||||
PORT_PHY_QCFG_RESP_PHY_ADDR_MASK;
|
PORT_PHY_QCFG_RESP_PHY_ADDR_MASK;
|
||||||
|
link_info->module_status = resp->module_status;
|
||||||
|
|
||||||
if (bp->flags & BNXT_FLAG_EEE_CAP) {
|
if (bp->flags & BNXT_FLAG_EEE_CAP) {
|
||||||
struct ethtool_eee *eee = &bp->eee;
|
struct ethtool_eee *eee = &bp->eee;
|
||||||
@ -4786,6 +4779,33 @@ static int bnxt_update_link(struct bnxt *bp, bool chng_link_state)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void bnxt_get_port_module_status(struct bnxt *bp)
|
||||||
|
{
|
||||||
|
struct bnxt_link_info *link_info = &bp->link_info;
|
||||||
|
struct hwrm_port_phy_qcfg_output *resp = &link_info->phy_qcfg_resp;
|
||||||
|
u8 module_status;
|
||||||
|
|
||||||
|
if (bnxt_update_link(bp, true))
|
||||||
|
return;
|
||||||
|
|
||||||
|
module_status = link_info->module_status;
|
||||||
|
switch (module_status) {
|
||||||
|
case PORT_PHY_QCFG_RESP_MODULE_STATUS_DISABLETX:
|
||||||
|
case PORT_PHY_QCFG_RESP_MODULE_STATUS_PWRDOWN:
|
||||||
|
case PORT_PHY_QCFG_RESP_MODULE_STATUS_WARNINGMSG:
|
||||||
|
netdev_warn(bp->dev, "Unqualified SFP+ module detected on port %d\n",
|
||||||
|
bp->pf.port_id);
|
||||||
|
if (bp->hwrm_spec_code >= 0x10201) {
|
||||||
|
netdev_warn(bp->dev, "Module part number %s\n",
|
||||||
|
resp->phy_vendor_partnumber);
|
||||||
|
}
|
||||||
|
if (module_status == PORT_PHY_QCFG_RESP_MODULE_STATUS_DISABLETX)
|
||||||
|
netdev_warn(bp->dev, "TX is disabled\n");
|
||||||
|
if (module_status == PORT_PHY_QCFG_RESP_MODULE_STATUS_PWRDOWN)
|
||||||
|
netdev_warn(bp->dev, "SFP+ module is shutdown\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bnxt_hwrm_set_pause_common(struct bnxt *bp, struct hwrm_port_phy_cfg_input *req)
|
bnxt_hwrm_set_pause_common(struct bnxt *bp, struct hwrm_port_phy_cfg_input *req)
|
||||||
{
|
{
|
||||||
@ -5078,7 +5098,8 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
|
|||||||
/* Enable TX queues */
|
/* Enable TX queues */
|
||||||
bnxt_tx_enable(bp);
|
bnxt_tx_enable(bp);
|
||||||
mod_timer(&bp->timer, jiffies + bp->current_interval);
|
mod_timer(&bp->timer, jiffies + bp->current_interval);
|
||||||
bnxt_update_link(bp, true);
|
/* Poll link status and check for SFP+ module status */
|
||||||
|
bnxt_get_port_module_status(bp);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -5613,28 +5634,6 @@ bnxt_restart_timer:
|
|||||||
mod_timer(&bp->timer, jiffies + bp->current_interval);
|
mod_timer(&bp->timer, jiffies + bp->current_interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bnxt_port_module_event(struct bnxt *bp)
|
|
||||||
{
|
|
||||||
struct bnxt_link_info *link_info = &bp->link_info;
|
|
||||||
struct hwrm_port_phy_qcfg_output *resp = &link_info->phy_qcfg_resp;
|
|
||||||
|
|
||||||
if (bnxt_update_link(bp, true))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (link_info->last_port_module_event != 0) {
|
|
||||||
netdev_warn(bp->dev, "Unqualified SFP+ module detected on port %d\n",
|
|
||||||
bp->pf.port_id);
|
|
||||||
if (bp->hwrm_spec_code >= 0x10201) {
|
|
||||||
netdev_warn(bp->dev, "Module part number %s\n",
|
|
||||||
resp->phy_vendor_partnumber);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (link_info->last_port_module_event == 1)
|
|
||||||
netdev_warn(bp->dev, "TX is disabled\n");
|
|
||||||
if (link_info->last_port_module_event == 3)
|
|
||||||
netdev_warn(bp->dev, "Shutdown SFP+ module\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void bnxt_cfg_ntp_filters(struct bnxt *);
|
static void bnxt_cfg_ntp_filters(struct bnxt *);
|
||||||
|
|
||||||
static void bnxt_sp_task(struct work_struct *work)
|
static void bnxt_sp_task(struct work_struct *work)
|
||||||
@ -5683,7 +5682,7 @@ static void bnxt_sp_task(struct work_struct *work)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (test_and_clear_bit(BNXT_HWRM_PORT_MODULE_SP_EVENT, &bp->sp_event))
|
if (test_and_clear_bit(BNXT_HWRM_PORT_MODULE_SP_EVENT, &bp->sp_event))
|
||||||
bnxt_port_module_event(bp);
|
bnxt_get_port_module_status(bp);
|
||||||
|
|
||||||
if (test_and_clear_bit(BNXT_PERIODIC_STATS_SP_EVENT, &bp->sp_event))
|
if (test_and_clear_bit(BNXT_PERIODIC_STATS_SP_EVENT, &bp->sp_event))
|
||||||
bnxt_hwrm_port_qstats(bp);
|
bnxt_hwrm_port_qstats(bp);
|
||||||
@ -6260,6 +6259,22 @@ static int bnxt_set_dflt_rings(struct bnxt *bp)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void bnxt_parse_log_pcie_link(struct bnxt *bp)
|
||||||
|
{
|
||||||
|
enum pcie_link_width width = PCIE_LNK_WIDTH_UNKNOWN;
|
||||||
|
enum pci_bus_speed speed = PCI_SPEED_UNKNOWN;
|
||||||
|
|
||||||
|
if (pcie_get_minimum_link(bp->pdev, &speed, &width) ||
|
||||||
|
speed == PCI_SPEED_UNKNOWN || width == PCIE_LNK_WIDTH_UNKNOWN)
|
||||||
|
netdev_info(bp->dev, "Failed to determine PCIe Link Info\n");
|
||||||
|
else
|
||||||
|
netdev_info(bp->dev, "PCIe: Speed %s Width x%d\n",
|
||||||
|
speed == PCIE_SPEED_2_5GT ? "2.5GT/s" :
|
||||||
|
speed == PCIE_SPEED_5_0GT ? "5.0GT/s" :
|
||||||
|
speed == PCIE_SPEED_8_0GT ? "8.0GT/s" :
|
||||||
|
"Unknown", width);
|
||||||
|
}
|
||||||
|
|
||||||
static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||||
{
|
{
|
||||||
static int version_printed;
|
static int version_printed;
|
||||||
@ -6380,6 +6395,8 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||||||
board_info[ent->driver_data].name,
|
board_info[ent->driver_data].name,
|
||||||
(long)pci_resource_start(pdev, 0), dev->dev_addr);
|
(long)pci_resource_start(pdev, 0), dev->dev_addr);
|
||||||
|
|
||||||
|
bnxt_parse_log_pcie_link(bp);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
init_err:
|
init_err:
|
||||||
|
@ -425,10 +425,17 @@ struct rx_tpa_end_cmp_ext {
|
|||||||
|
|
||||||
#define MAX_TPA 64
|
#define MAX_TPA 64
|
||||||
|
|
||||||
|
#if (BNXT_PAGE_SHIFT == 16)
|
||||||
|
#define MAX_RX_PAGES 1
|
||||||
|
#define MAX_RX_AGG_PAGES 4
|
||||||
|
#define MAX_TX_PAGES 1
|
||||||
|
#define MAX_CP_PAGES 8
|
||||||
|
#else
|
||||||
#define MAX_RX_PAGES 8
|
#define MAX_RX_PAGES 8
|
||||||
#define MAX_RX_AGG_PAGES 32
|
#define MAX_RX_AGG_PAGES 32
|
||||||
#define MAX_TX_PAGES 8
|
#define MAX_TX_PAGES 8
|
||||||
#define MAX_CP_PAGES 64
|
#define MAX_CP_PAGES 64
|
||||||
|
#endif
|
||||||
|
|
||||||
#define RX_DESC_CNT (BNXT_PAGE_SIZE / sizeof(struct rx_bd))
|
#define RX_DESC_CNT (BNXT_PAGE_SIZE / sizeof(struct rx_bd))
|
||||||
#define TX_DESC_CNT (BNXT_PAGE_SIZE / sizeof(struct tx_bd))
|
#define TX_DESC_CNT (BNXT_PAGE_SIZE / sizeof(struct tx_bd))
|
||||||
@ -831,6 +838,7 @@ struct bnxt_link_info {
|
|||||||
u16 lp_auto_link_speeds;
|
u16 lp_auto_link_speeds;
|
||||||
u16 force_link_speed;
|
u16 force_link_speed;
|
||||||
u32 preemphasis;
|
u32 preemphasis;
|
||||||
|
u8 module_status;
|
||||||
|
|
||||||
/* copy of requested setting from ethtool cmd */
|
/* copy of requested setting from ethtool cmd */
|
||||||
u8 autoneg;
|
u8 autoneg;
|
||||||
@ -842,7 +850,6 @@ struct bnxt_link_info {
|
|||||||
u32 advertising;
|
u32 advertising;
|
||||||
bool force_link_chng;
|
bool force_link_chng;
|
||||||
|
|
||||||
u8 last_port_module_event;
|
|
||||||
/* a copy of phy_qcfg output used to report link
|
/* a copy of phy_qcfg output used to report link
|
||||||
* info to VF
|
* info to VF
|
||||||
*/
|
*/
|
||||||
@ -1123,6 +1130,16 @@ static inline void bnxt_disable_poll(struct bnxt_napi *bnapi)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define I2C_DEV_ADDR_A0 0xa0
|
||||||
|
#define I2C_DEV_ADDR_A2 0xa2
|
||||||
|
#define SFP_EEPROM_SFF_8472_COMP_ADDR 0x5e
|
||||||
|
#define SFP_EEPROM_SFF_8472_COMP_SIZE 1
|
||||||
|
#define SFF_MODULE_ID_SFP 0x3
|
||||||
|
#define SFF_MODULE_ID_QSFP 0xc
|
||||||
|
#define SFF_MODULE_ID_QSFP_PLUS 0xd
|
||||||
|
#define SFF_MODULE_ID_QSFP28 0x11
|
||||||
|
#define BNXT_MAX_PHY_I2C_RESP_SIZE 64
|
||||||
|
|
||||||
void bnxt_set_ring_params(struct bnxt *);
|
void bnxt_set_ring_params(struct bnxt *);
|
||||||
void bnxt_hwrm_cmd_hdr_init(struct bnxt *, void *, u16, u16, u16);
|
void bnxt_hwrm_cmd_hdr_init(struct bnxt *, void *, u16, u16, u16);
|
||||||
int _hwrm_send_message(struct bnxt *, void *, u32, int);
|
int _hwrm_send_message(struct bnxt *, void *, u32, int);
|
||||||
|
@ -327,7 +327,11 @@ static void bnxt_get_channels(struct net_device *dev,
|
|||||||
bnxt_get_max_rings(bp, &max_rx_rings, &max_tx_rings, true);
|
bnxt_get_max_rings(bp, &max_rx_rings, &max_tx_rings, true);
|
||||||
channel->max_combined = max_rx_rings;
|
channel->max_combined = max_rx_rings;
|
||||||
|
|
||||||
bnxt_get_max_rings(bp, &max_rx_rings, &max_tx_rings, false);
|
if (bnxt_get_max_rings(bp, &max_rx_rings, &max_tx_rings, false)) {
|
||||||
|
max_rx_rings = 0;
|
||||||
|
max_tx_rings = 0;
|
||||||
|
}
|
||||||
|
|
||||||
tcs = netdev_get_num_tc(dev);
|
tcs = netdev_get_num_tc(dev);
|
||||||
if (tcs > 1)
|
if (tcs > 1)
|
||||||
max_tx_rings /= tcs;
|
max_tx_rings /= tcs;
|
||||||
@ -1494,6 +1498,125 @@ static int bnxt_get_eee(struct net_device *dev, struct ethtool_eee *edata)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int bnxt_read_sfp_module_eeprom_info(struct bnxt *bp, u16 i2c_addr,
|
||||||
|
u16 page_number, u16 start_addr,
|
||||||
|
u16 data_length, u8 *buf)
|
||||||
|
{
|
||||||
|
struct hwrm_port_phy_i2c_read_input req = {0};
|
||||||
|
struct hwrm_port_phy_i2c_read_output *output = bp->hwrm_cmd_resp_addr;
|
||||||
|
int rc, byte_offset = 0;
|
||||||
|
|
||||||
|
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_PHY_I2C_READ, -1, -1);
|
||||||
|
req.i2c_slave_addr = i2c_addr;
|
||||||
|
req.page_number = cpu_to_le16(page_number);
|
||||||
|
req.port_id = cpu_to_le16(bp->pf.port_id);
|
||||||
|
do {
|
||||||
|
u16 xfer_size;
|
||||||
|
|
||||||
|
xfer_size = min_t(u16, data_length, BNXT_MAX_PHY_I2C_RESP_SIZE);
|
||||||
|
data_length -= xfer_size;
|
||||||
|
req.page_offset = cpu_to_le16(start_addr + byte_offset);
|
||||||
|
req.data_length = xfer_size;
|
||||||
|
req.enables = cpu_to_le32(start_addr + byte_offset ?
|
||||||
|
PORT_PHY_I2C_READ_REQ_ENABLES_PAGE_OFFSET : 0);
|
||||||
|
mutex_lock(&bp->hwrm_cmd_lock);
|
||||||
|
rc = _hwrm_send_message(bp, &req, sizeof(req),
|
||||||
|
HWRM_CMD_TIMEOUT);
|
||||||
|
if (!rc)
|
||||||
|
memcpy(buf + byte_offset, output->data, xfer_size);
|
||||||
|
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||||
|
byte_offset += xfer_size;
|
||||||
|
} while (!rc && data_length > 0);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bnxt_get_module_info(struct net_device *dev,
|
||||||
|
struct ethtool_modinfo *modinfo)
|
||||||
|
{
|
||||||
|
struct bnxt *bp = netdev_priv(dev);
|
||||||
|
struct hwrm_port_phy_i2c_read_input req = {0};
|
||||||
|
struct hwrm_port_phy_i2c_read_output *output = bp->hwrm_cmd_resp_addr;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* No point in going further if phy status indicates
|
||||||
|
* module is not inserted or if it is powered down or
|
||||||
|
* if it is of type 10GBase-T
|
||||||
|
*/
|
||||||
|
if (bp->link_info.module_status >
|
||||||
|
PORT_PHY_QCFG_RESP_MODULE_STATUS_WARNINGMSG)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
/* This feature is not supported in older firmware versions */
|
||||||
|
if (bp->hwrm_spec_code < 0x10202)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_PHY_I2C_READ, -1, -1);
|
||||||
|
req.i2c_slave_addr = I2C_DEV_ADDR_A0;
|
||||||
|
req.page_number = 0;
|
||||||
|
req.page_offset = cpu_to_le16(SFP_EEPROM_SFF_8472_COMP_ADDR);
|
||||||
|
req.data_length = SFP_EEPROM_SFF_8472_COMP_SIZE;
|
||||||
|
req.port_id = cpu_to_le16(bp->pf.port_id);
|
||||||
|
mutex_lock(&bp->hwrm_cmd_lock);
|
||||||
|
rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
|
||||||
|
if (!rc) {
|
||||||
|
u32 module_id = le32_to_cpu(output->data[0]);
|
||||||
|
|
||||||
|
switch (module_id) {
|
||||||
|
case SFF_MODULE_ID_SFP:
|
||||||
|
modinfo->type = ETH_MODULE_SFF_8472;
|
||||||
|
modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
|
||||||
|
break;
|
||||||
|
case SFF_MODULE_ID_QSFP:
|
||||||
|
case SFF_MODULE_ID_QSFP_PLUS:
|
||||||
|
modinfo->type = ETH_MODULE_SFF_8436;
|
||||||
|
modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;
|
||||||
|
break;
|
||||||
|
case SFF_MODULE_ID_QSFP28:
|
||||||
|
modinfo->type = ETH_MODULE_SFF_8636;
|
||||||
|
modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rc = -EOPNOTSUPP;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mutex_unlock(&bp->hwrm_cmd_lock);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bnxt_get_module_eeprom(struct net_device *dev,
|
||||||
|
struct ethtool_eeprom *eeprom,
|
||||||
|
u8 *data)
|
||||||
|
{
|
||||||
|
struct bnxt *bp = netdev_priv(dev);
|
||||||
|
u16 start = eeprom->offset, length = eeprom->len;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
memset(data, 0, eeprom->len);
|
||||||
|
|
||||||
|
/* Read A0 portion of the EEPROM */
|
||||||
|
if (start < ETH_MODULE_SFF_8436_LEN) {
|
||||||
|
if (start + eeprom->len > ETH_MODULE_SFF_8436_LEN)
|
||||||
|
length = ETH_MODULE_SFF_8436_LEN - start;
|
||||||
|
rc = bnxt_read_sfp_module_eeprom_info(bp, I2C_DEV_ADDR_A0, 0,
|
||||||
|
start, length, data);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
start += length;
|
||||||
|
data += length;
|
||||||
|
length = eeprom->len - length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read A2 portion of the EEPROM */
|
||||||
|
if (length) {
|
||||||
|
start -= ETH_MODULE_SFF_8436_LEN;
|
||||||
|
bnxt_read_sfp_module_eeprom_info(bp, I2C_DEV_ADDR_A2, 1, start,
|
||||||
|
length, data);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
const struct ethtool_ops bnxt_ethtool_ops = {
|
const struct ethtool_ops bnxt_ethtool_ops = {
|
||||||
.get_settings = bnxt_get_settings,
|
.get_settings = bnxt_get_settings,
|
||||||
.set_settings = bnxt_set_settings,
|
.set_settings = bnxt_set_settings,
|
||||||
@ -1524,4 +1647,6 @@ const struct ethtool_ops bnxt_ethtool_ops = {
|
|||||||
.get_link = bnxt_get_link,
|
.get_link = bnxt_get_link,
|
||||||
.get_eee = bnxt_get_eee,
|
.get_eee = bnxt_get_eee,
|
||||||
.set_eee = bnxt_set_eee,
|
.set_eee = bnxt_set_eee,
|
||||||
|
.get_module_info = bnxt_get_module_info,
|
||||||
|
.get_module_eeprom = bnxt_get_module_eeprom,
|
||||||
};
|
};
|
||||||
|
@ -2093,6 +2093,40 @@ struct hwrm_port_phy_qcaps_output {
|
|||||||
#define PORT_PHY_QCAPS_RESP_VALID_SFT 24
|
#define PORT_PHY_QCAPS_RESP_VALID_SFT 24
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* hwrm_port_phy_i2c_read */
|
||||||
|
/* Input (40 bytes) */
|
||||||
|
struct hwrm_port_phy_i2c_read_input {
|
||||||
|
__le16 req_type;
|
||||||
|
__le16 cmpl_ring;
|
||||||
|
__le16 seq_id;
|
||||||
|
__le16 target_id;
|
||||||
|
__le64 resp_addr;
|
||||||
|
__le32 flags;
|
||||||
|
__le32 enables;
|
||||||
|
#define PORT_PHY_I2C_READ_REQ_ENABLES_PAGE_OFFSET 0x1UL
|
||||||
|
__le16 port_id;
|
||||||
|
u8 i2c_slave_addr;
|
||||||
|
u8 unused_0;
|
||||||
|
__le16 page_number;
|
||||||
|
__le16 page_offset;
|
||||||
|
u8 data_length;
|
||||||
|
u8 unused_1[7];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Output (80 bytes) */
|
||||||
|
struct hwrm_port_phy_i2c_read_output {
|
||||||
|
__le16 error_code;
|
||||||
|
__le16 req_type;
|
||||||
|
__le16 seq_id;
|
||||||
|
__le16 resp_len;
|
||||||
|
__le32 data[16];
|
||||||
|
__le32 unused_0;
|
||||||
|
u8 unused_1;
|
||||||
|
u8 unused_2;
|
||||||
|
u8 unused_3;
|
||||||
|
u8 valid;
|
||||||
|
};
|
||||||
|
|
||||||
/* Input (24 bytes) */
|
/* Input (24 bytes) */
|
||||||
struct hwrm_queue_qportcfg_input {
|
struct hwrm_queue_qportcfg_input {
|
||||||
__le16 req_type;
|
__le16 req_type;
|
||||||
|
Loading…
Reference in New Issue
Block a user