/* Send and ACK mailbox command to the firmware to * let it continue with the change. */ static int ql_mb_idc_ack(struct ql_adapter *qdev) { struct mbox_params mbc; struct mbox_params *mbcp = &mbc; int status = 0; memset(mbcp, 0, sizeof(struct mbox_params)); mbcp->in_count = 5; mbcp->out_count = 1; mbcp->mbox_in[0] = MB_CMD_IDC_ACK; mbcp->mbox_in[1] = qdev->idc_mbc.mbox_out[1]; mbcp->mbox_in[2] = qdev->idc_mbc.mbox_out[2]; mbcp->mbox_in[3] = qdev->idc_mbc.mbox_out[3]; mbcp->mbox_in[4] = qdev->idc_mbc.mbox_out[4]; status = ql_mailbox_command(qdev, mbcp); if (status) return status; if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { netif_err(qdev, drv, qdev->ndev, "Failed IDC ACK send.\n"); status = -EIO; } return status; }
/* * Allocate a page worth of efx_tso_header structures, and string them * into the tx_queue->tso_headers_free linked list. Return 0 or -ENOMEM. */ static int efx_tsoh_block_alloc(struct efx_tx_queue *tx_queue) { struct pci_dev *pci_dev = tx_queue->efx->pci_dev; struct efx_tso_header *tsoh; dma_addr_t dma_addr; u8 *base_kva, *kva; base_kva = pci_alloc_consistent(pci_dev, PAGE_SIZE, &dma_addr); if (base_kva == NULL) { netif_err(tx_queue->efx, tx_err, tx_queue->efx->net_dev, "Unable to allocate page for TSO headers\n"); return -ENOMEM; } /* pci_alloc_consistent() allocates pages. */ EFX_BUG_ON_PARANOID(dma_addr & (PAGE_SIZE - 1u)); for (kva = base_kva; kva < base_kva + PAGE_SIZE; kva += TSOH_STD_SIZE) { tsoh = (struct efx_tso_header *)kva; tsoh->dma_addr = dma_addr + (TSOH_BUFFER(tsoh) - base_kva); tsoh->next = tx_queue->tso_headers_free; tx_queue->tso_headers_free = tsoh; } return 0; }
static int ql_mb_dump_ram(struct ql_adapter *qdev, u64 req_dma, u32 addr, u32 size) { int status = 0; struct mbox_params mbc; struct mbox_params *mbcp = &mbc; memset(mbcp, 0, sizeof(struct mbox_params)); mbcp->in_count = 9; mbcp->out_count = 1; mbcp->mbox_in[0] = MB_CMD_DUMP_RISC_RAM; mbcp->mbox_in[1] = LSW(addr); mbcp->mbox_in[2] = MSW(req_dma); mbcp->mbox_in[3] = LSW(req_dma); mbcp->mbox_in[4] = MSW(size); mbcp->mbox_in[5] = LSW(size); mbcp->mbox_in[6] = MSW(MSD(req_dma)); mbcp->mbox_in[7] = LSW(MSD(req_dma)); mbcp->mbox_in[8] = MSW(addr); status = ql_mailbox_command(qdev, mbcp); if (status) return status; if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { netif_err(qdev, drv, qdev->ndev, "Failed to dump risc RAM.\n"); status = -EIO; } return status; }
static void intr_complete (struct urb *urb) { struct usbnet *dev = urb->context; int status = urb->status; switch (status) { case 0: dev->driver_info->status(dev, urb); break; case -ENOENT: case -ESHUTDOWN: netif_dbg(dev, ifdown, dev->net, "intr shutdown, code %d\n", status); return; default: netdev_dbg(dev->net, "intr status %d\n", status); break; } if (!netif_running (dev->net)) return; memset(urb->transfer_buffer, 0, urb->transfer_buffer_length); status = usb_submit_urb (urb, GFP_ATOMIC); if (status != 0) netif_err(dev, timer, dev->net, "intr resubmit --> %d\n", status); }
/* Get MPI firmware version. This will be used for * driver banner and for ethtool info. * Returns zero on success. */ int ql_mb_about_fw(struct ql_adapter *qdev) { struct mbox_params mbc; struct mbox_params *mbcp = &mbc; int status = 0; memset(mbcp, 0, sizeof(struct mbox_params)); mbcp->in_count = 1; mbcp->out_count = 3; mbcp->mbox_in[0] = MB_CMD_ABOUT_FW; status = ql_mailbox_command(qdev, mbcp); if (status) return status; if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { netif_err(qdev, drv, qdev->ndev, "Failed about firmware command\n"); status = -EIO; } /* Store the firmware version */ qdev->fw_rev_id = mbcp->mbox_out[1]; return status; }
static void intr_complete (struct urb *urb) { struct usbnet *dev = urb->context; int status = urb->status; switch (status) { /* success */ case 0: dev->driver_info->status(dev, urb); break; /* software-driven interface shutdown */ case -ENOENT: /* urb killed */ case -ESHUTDOWN: /* hardware gone */ netif_dbg(dev, ifdown, dev->net, "intr shutdown, code %d\n", status); return; /* NOTE: not throttling like RX/TX, since this endpoint * already polls infrequently */ default: netdev_dbg(dev->net, "intr status %d\n", status); break; } if (!netif_running (dev->net)) return; memset(urb->transfer_buffer, 0, urb->transfer_buffer_length); status = usb_submit_urb (urb, GFP_ATOMIC); if (status != 0) netif_err(dev, timer, dev->net, "intr resubmit --> %d\n", status); }
static int efx_mcdi_loopback_modes(struct efx_nic *efx, u64 *loopback_modes) { MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_LOOPBACK_MODES_OUT_LEN); size_t outlen; int rc; rc = efx_mcdi_rpc(efx, MC_CMD_GET_LOOPBACK_MODES, NULL, 0, outbuf, sizeof(outbuf), &outlen); if (rc) goto fail; if (outlen < (MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_OFST + MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_LEN)) { rc = -EIO; goto fail; } *loopback_modes = MCDI_QWORD(outbuf, GET_LOOPBACK_MODES_OUT_SUGGESTED); return 0; fail: netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return rc; }
static int efx_ef10_pci_sriov_enable(struct efx_nic *efx, int num_vfs) { struct pci_dev *dev = efx->pci_dev; int rc; efx->vf_count = num_vfs; rc = efx_ef10_sriov_alloc_vf_vswitching(efx); if (rc) goto fail1; rc = pci_enable_sriov(dev, num_vfs); if (rc) goto fail2; return 0; fail2: efx_ef10_sriov_free_vf_vswitching(efx); fail1: efx->vf_count = 0; netif_err(efx, probe, efx->net_dev, "Failed to enable SRIOV VFs\n"); return rc; }
/* Remove packets from the TX queue * * This removes packets from the TX queue, up to and including the * specified index. */ static void efx_dequeue_buffers(struct efx_tx_queue *tx_queue, unsigned int index) { struct efx_nic *efx = tx_queue->efx; unsigned int stop_index, read_ptr; stop_index = (index + 1) & tx_queue->ptr_mask; read_ptr = tx_queue->read_count & tx_queue->ptr_mask; while (read_ptr != stop_index) { struct efx_tx_buffer *buffer = &tx_queue->buffer[read_ptr]; if (unlikely(buffer->len == 0)) { netif_err(efx, tx_err, efx->net_dev, "TX queue %d spurious TX completion id %x\n", tx_queue->queue, read_ptr); efx_schedule_reset(efx, RESET_TYPE_TX_SKIP); return; } efx_dequeue_buffer(tx_queue, buffer); buffer->continuation = true; buffer->len = 0; ++tx_queue->read_count; read_ptr = tx_queue->read_count & tx_queue->ptr_mask; } }
int efx_mcdi_reset_port(struct efx_nic *efx) { int rc = efx_mcdi_rpc(efx, MC_CMD_PORT_RESET, NULL, 0, NULL, 0, NULL); if (rc) netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return rc; }
static void ql_link_up(struct ql_adapter *qdev, struct mbox_params *mbcp) { int status; mbcp->out_count = 2; status = ql_get_mb_sts(qdev, mbcp); if (status) { netif_err(qdev, drv, qdev->ndev, "%s: Could not get mailbox status.\n", __func__); return; } qdev->link_status = mbcp->mbox_out[1]; netif_err(qdev, drv, qdev->ndev, "Link Up.\n"); /* If we're coming back from an IDC event * then set up the CAM and frame routing. */ if (test_bit(QL_CAM_RT_SET, &qdev->flags)) { status = ql_cam_route_initialize(qdev); if (status) { netif_err(qdev, ifup, qdev->ndev, "Failed to init CAM/Routing tables.\n"); return; } else clear_bit(QL_CAM_RT_SET, &qdev->flags); } /* Queue up a worker to check the frame * size information, and fix it if it's not * to our liking. */ if (!test_bit(QL_PORT_CFG, &qdev->flags)) { netif_err(qdev, drv, qdev->ndev, "Queue Port Config Worker!\n"); set_bit(QL_PORT_CFG, &qdev->flags); /* Begin polled mode early so * we don't get another interrupt * when we leave mpi_worker dpc. */ ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16)); queue_delayed_work(qdev->workqueue, &qdev->mpi_port_cfg_work, 0); } ql_link_on(qdev); }
int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv, enum bcmgenet_power_mode mode) { struct net_device *dev = priv->dev; u32 cpu_mask_clear; int retries = 0; u32 reg; if (mode != GENET_POWER_WOL_MAGIC) { netif_err(priv, wol, dev, "unsupported mode: %d\n", mode); return -EINVAL; } /* disable RX */ reg = bcmgenet_umac_readl(priv, UMAC_CMD); reg &= ~CMD_RX_EN; bcmgenet_umac_writel(priv, reg, UMAC_CMD); mdelay(10); reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL); reg |= MPD_EN; bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL); /* Do not leave UniMAC in MPD mode only */ retries = bcmgenet_poll_wol_status(priv); if (retries < 0) { reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL); reg &= ~MPD_EN; bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL); return retries; } netif_dbg(priv, wol, dev, "MPD WOL-ready status set after %d msec\n", retries); /* Enable CRC forward */ reg = bcmgenet_umac_readl(priv, UMAC_CMD); priv->crc_fwd_en = 1; reg |= CMD_CRC_FWD; /* Receiver must be enabled for WOL MP detection */ reg |= CMD_RX_EN; bcmgenet_umac_writel(priv, reg, UMAC_CMD); if (priv->hw_params->flags & GENET_HAS_EXT) { reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT); reg &= ~EXT_ENERGY_DET_MASK; bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT); } /* Enable the MPD interrupt */ cpu_mask_clear = UMAC_IRQ_MPD_R; bcmgenet_intrl2_0_writel(priv, cpu_mask_clear, INTRL2_CPU_MASK_CLEAR); return 0; }
static int falcon_probe_port(struct efx_nic *efx) { struct falcon_nic_data *nic_data = efx->nic_data; int rc; switch (efx->phy_type) { case PHY_TYPE_SFX7101: efx->phy_op = &falcon_sfx7101_phy_ops; break; case PHY_TYPE_QT2022C2: case PHY_TYPE_QT2025C: efx->phy_op = &falcon_qt202x_phy_ops; break; case PHY_TYPE_TXC43128: efx->phy_op = &falcon_txc_phy_ops; break; default: netif_err(efx, probe, efx->net_dev, "Unknown PHY type %d\n", efx->phy_type); return -ENODEV; } mutex_init(&nic_data->mdio_lock); efx->mdio.mdio_read = falcon_mdio_read; efx->mdio.mdio_write = falcon_mdio_write; rc = efx->phy_op->probe(efx); if (rc != 0) return rc; efx->link_state.speed = 10000; efx->link_state.fd = true; if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) efx->wanted_fc = EFX_FC_RX | EFX_FC_TX; else efx->wanted_fc = EFX_FC_RX; if (efx->mdio.mmds & MDIO_DEVS_AN) efx->wanted_fc |= EFX_FC_AUTO; rc = efx_nic_alloc_buffer(efx, &efx->stats_buffer, FALCON_MAC_STATS_SIZE); if (rc) return rc; netif_dbg(efx, probe, efx->net_dev, "stats buffer at %llx (virt %p phys %llx)\n", (u64)efx->stats_buffer.dma_addr, efx->stats_buffer.addr, (u64)virt_to_phys(efx->stats_buffer.addr)); nic_data->stats_dma_done = efx->stats_buffer.addr + XgDmaDone_offset; return 0; }
static void ql_init_fw_done(struct ql_adapter *qdev, struct mbox_params *mbcp) { int status; mbcp->out_count = 2; status = ql_get_mb_sts(qdev, mbcp); if (status) { netif_err(qdev, drv, qdev->ndev, "Firmware did not initialize!\n"); } else { netif_err(qdev, drv, qdev->ndev, "Firmware Revision = 0x%.08x.\n", mbcp->mbox_out[1]); qdev->fw_rev_id = mbcp->mbox_out[1]; status = ql_cam_route_initialize(qdev); if (status) netif_err(qdev, ifup, qdev->ndev, "Failed to init CAM/Routing tables.\n"); } }
static int ql_aen_lost(struct ql_adapter *qdev, struct mbox_params *mbcp) { int status; mbcp->out_count = 6; status = ql_get_mb_sts(qdev, mbcp); if (status) netif_err(qdev, drv, qdev->ndev, "Lost AEN broken!\n"); else { int i; netif_err(qdev, drv, qdev->ndev, "Lost AEN detected.\n"); for (i = 0; i < mbcp->out_count; i++) netif_err(qdev, drv, qdev->ndev, "mbox_out[%d] = 0x%.08x.\n", i, mbcp->mbox_out[i]); } return status; }
static void ql_link_down(struct ql_adapter *qdev, struct mbox_params *mbcp) { int status; mbcp->out_count = 3; status = ql_get_mb_sts(qdev, mbcp); if (status) netif_err(qdev, drv, qdev->ndev, "Link down AEN broken!\n"); ql_link_off(qdev); }
int efx_mcdi_wol_filter_reset(struct efx_nic *efx) { int rc; rc = efx_mcdi_rpc(efx, MC_CMD_WOL_FILTER_RESET, NULL, 0, NULL, 0, NULL); if (rc) goto fail; return 0; fail: netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return rc; }
static int falcon_gmii_wait(struct efx_nic *efx) { efx_oword_t md_stat; int count; for (count = 0; count < 5000; count++) { efx_reado(efx, &md_stat, FR_AB_MD_STAT); if (EFX_OWORD_FIELD(md_stat, FRF_AB_MD_BSY) == 0) { if (EFX_OWORD_FIELD(md_stat, FRF_AB_MD_LNFL) != 0 || EFX_OWORD_FIELD(md_stat, FRF_AB_MD_BSERR) != 0) { netif_err(efx, hw, efx->net_dev, "error from GMII access " EFX_OWORD_FMT"\n", EFX_OWORD_VAL(md_stat)); return -EIO; } return 0; } udelay(10); } netif_err(efx, hw, efx->net_dev, "timed out waiting for GMII\n"); return -ETIMEDOUT; }
/* IDC - Inter Device Communication... * Some firmware commands require consent of adjacent FCOE * function. This function waits for the OK, or a * counter-request for a little more time.i * The firmware will complete the request if the other * function doesn't respond. */ static int ql_idc_wait(struct ql_adapter *qdev) { int status = -ETIMEDOUT; long wait_time = 1 * HZ; struct mbox_params *mbcp = &qdev->idc_mbc; do { /* Wait here for the command to complete * via the IDC process. */ wait_time = wait_for_completion_timeout(&qdev->ide_completion, wait_time); if (!wait_time) { netif_err(qdev, drv, qdev->ndev, "IDC Timeout.\n"); break; } /* Now examine the response from the IDC process. * We might have a good completion or a request for * more wait time. */ if (mbcp->mbox_out[0] == AEN_IDC_EXT) { netif_err(qdev, drv, qdev->ndev, "IDC Time Extension from function.\n"); wait_time += (mbcp->mbox_out[1] >> 8) & 0x0000000f; } else if (mbcp->mbox_out[0] == AEN_IDC_CMPLT) { netif_err(qdev, drv, qdev->ndev, "IDC Success.\n"); status = 0; break; } else { netif_err(qdev, drv, qdev->ndev, "IDC: Invalid State 0x%.04x.\n", mbcp->mbox_out[0]); status = -EIO; break; } } while (wait_time);
static void falcon_stats_complete(struct efx_nic *efx) { struct falcon_nic_data *nic_data = efx->nic_data; if (!nic_data->stats_pending) return; nic_data->stats_pending = false; if (*nic_data->stats_dma_done == FALCON_STATS_DONE) { rmb(); falcon_update_stats_xmac(efx); } else { netif_err(efx, hw, efx->net_dev, "timed out waiting for statistics\n"); } }
static void falcon_stats_complete(struct efx_nic *efx) { struct falcon_nic_data *nic_data = efx->nic_data; if (!nic_data->stats_pending) return; nic_data->stats_pending = 0; if (*nic_data->stats_dma_done == FALCON_STATS_DONE) { rmb(); /* read the done flag before the stats */ efx->mac_op->update_stats(efx); } else { netif_err(efx, hw, efx->net_dev, "timed out waiting for statistics\n"); } }
int efx_mcdi_reset_mc(struct efx_nic *efx) { u8 inbuf[MC_CMD_REBOOT_IN_LEN]; int rc; BUILD_BUG_ON(MC_CMD_REBOOT_OUT_LEN != 0); MCDI_SET_DWORD(inbuf, REBOOT_IN_FLAGS, 0); rc = efx_mcdi_rpc(efx, MC_CMD_REBOOT, inbuf, sizeof(inbuf), NULL, 0, NULL); /* White is black, and up is down */ if (rc == -EIO) return 0; if (rc == 0) rc = -EIO; netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return rc; }
static void fm10k_self_test(struct net_device *dev, struct ethtool_test *eth_test, u64 *data) { struct fm10k_intfc *interface = netdev_priv(dev); struct fm10k_hw *hw = &interface->hw; memset(data, 0, sizeof(*data) * FM10K_TEST_LEN); if (FM10K_REMOVED(hw)) { netif_err(interface, drv, dev, "Interface removed - test blocked\n"); eth_test->flags |= ETH_TEST_FL_FAILED; return; } if (fm10k_mbx_test(interface, &data[FM10K_TEST_MBX])) eth_test->flags |= ETH_TEST_FL_FAILED; }
/* Process an inter-device event completion. * If good, signal the caller's completion. */ static int ql_idc_cmplt_aen(struct ql_adapter *qdev) { int status; struct mbox_params *mbcp = &qdev->idc_mbc; mbcp->out_count = 4; status = ql_get_mb_sts(qdev, mbcp); if (status) { netif_err(qdev, drv, qdev->ndev, "Could not read MPI, resetting RISC!\n"); ql_queue_fw_error(qdev); } else /* Wake up the sleeping mpi_idc_work thread that is * waiting for this event. */ complete(&qdev->ide_completion); return status; }
bool efx_mcdi_mac_check_fault(struct efx_nic *efx) { u8 outbuf[MC_CMD_GET_LINK_OUT_LEN]; size_t outlength; int rc; BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0); rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0, outbuf, sizeof(outbuf), &outlength); if (rc) { netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return true; } return MCDI_DWORD(outbuf, GET_LINK_OUT_MAC_FAULT) != 0; }
int efx_mcdi_wol_filter_remove(struct efx_nic *efx, int id) { u8 inbuf[MC_CMD_WOL_FILTER_REMOVE_IN_LEN]; int rc; MCDI_SET_DWORD(inbuf, WOL_FILTER_REMOVE_IN_FILTER_ID, (u32)id); rc = efx_mcdi_rpc(efx, MC_CMD_WOL_FILTER_REMOVE, inbuf, sizeof(inbuf), NULL, 0, NULL); if (rc) goto fail; return 0; fail: netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); return rc; }
static int ql_get_mb_sts(struct ql_adapter *qdev, struct mbox_params *mbcp) { int i, status; status = ql_sem_spinlock(qdev, SEM_PROC_REG_MASK); if (status) return -EBUSY; for (i = 0; i < mbcp->out_count; i++) { status = ql_read_mpi_reg(qdev, qdev->mailbox_out + i, &mbcp->mbox_out[i]); if (status) { netif_err(qdev, drv, qdev->ndev, "Failed mailbox read.\n"); break; } } ql_sem_unlock(qdev, SEM_PROC_REG_MASK); /* does flush too */ return status; }
static void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev) { unsigned int monitor, state, value; const char *name, *state_txt; monitor = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_MONITOR); state = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_STATE); value = EFX_QWORD_FIELD(*ev, MCDI_EVENT_SENSOREVT_VALUE); /* Deal gracefully with the board having more drivers than we * know about, but do not expect new sensor states. */ name = (monitor >= ARRAY_SIZE(sensor_names)) ? "No sensor name available" : sensor_names[monitor]; EFX_BUG_ON_PARANOID(state >= ARRAY_SIZE(sensor_status_names)); state_txt = sensor_status_names[state]; netif_err(efx, hw, efx->net_dev, "Sensor %d (%s) reports condition '%s' for raw value %d\n", monitor, name, state_txt, value); }
static int ena_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *info) { struct ena_adapter *adapter = netdev_priv(netdev); int rc = 0; switch (info->cmd) { case ETHTOOL_SRXFH: rc = ena_set_rss_hash(adapter->ena_dev, info); break; case ETHTOOL_SRXCLSRLDEL: case ETHTOOL_SRXCLSRLINS: default: netif_err(adapter, drv, netdev, "Command parameter %d is not supported\n", info->cmd); rc = -EOPNOTSUPP; } return (rc == -EPERM) ? -EOPNOTSUPP : rc; }
void efx_mcdi_set_id_led(struct efx_nic *efx, enum efx_led_mode mode) { u8 inbuf[MC_CMD_SET_ID_LED_IN_LEN]; int rc; BUILD_BUG_ON(EFX_LED_OFF != MC_CMD_LED_OFF); BUILD_BUG_ON(EFX_LED_ON != MC_CMD_LED_ON); BUILD_BUG_ON(EFX_LED_DEFAULT != MC_CMD_LED_DEFAULT); BUILD_BUG_ON(MC_CMD_SET_ID_LED_OUT_LEN != 0); MCDI_SET_DWORD(inbuf, SET_ID_LED_IN_STATE, mode); rc = efx_mcdi_rpc(efx, MC_CMD_SET_ID_LED, inbuf, sizeof(inbuf), NULL, 0, NULL); if (rc) netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); }