forked from deepin-community/kernel
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
gve: Add basic driver framework for Compute Engine Virtual NIC
Add a driver framework for the Compute Engine Virtual NIC that will be available in the future. At this point the only functionality is loading the driver. Signed-off-by: Catherine Sullivan <csully@google.com> Signed-off-by: Sagi Shahar <sagis@google.com> Signed-off-by: Jon Olson <jonolson@google.com> Acked-by: Willem de Bruijn <willemb@google.com> Reviewed-by: Luigi Rizzo <lrizzo@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
- Loading branch information
1 parent
2a8d8e0
commit 893ce44
Showing
13 changed files
with
1,121 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
.. SPDX-License-Identifier: GPL-2.0+ | ||
============================================================== | ||
Linux kernel driver for Compute Engine Virtual Ethernet (gve): | ||
============================================================== | ||
|
||
Supported Hardware | ||
=================== | ||
The GVE driver binds to a single PCI device id used by the virtual | ||
Ethernet device found in some Compute Engine VMs. | ||
|
||
+--------------+----------+---------+ | ||
|Field | Value | Comments| | ||
+==============+==========+=========+ | ||
|Vendor ID | `0x1AE0` | Google | | ||
+--------------+----------+---------+ | ||
|Device ID | `0x0042` | | | ||
+--------------+----------+---------+ | ||
|Sub-vendor ID | `0x1AE0` | Google | | ||
+--------------+----------+---------+ | ||
|Sub-device ID | `0x0058` | | | ||
+--------------+----------+---------+ | ||
|Revision ID | `0x0` | | | ||
+--------------+----------+---------+ | ||
|Device Class | `0x200` | Ethernet| | ||
+--------------+----------+---------+ | ||
|
||
PCI Bars | ||
======== | ||
The gVNIC PCI device exposes three 32-bit memory BARS: | ||
- Bar0 - Device configuration and status registers. | ||
- Bar1 - MSI-X vector table | ||
- Bar2 - IRQ, RX and TX doorbells | ||
|
||
Device Interactions | ||
=================== | ||
The driver interacts with the device in the following ways: | ||
- Registers | ||
- A block of MMIO registers | ||
- See gve_register.h for more detail | ||
- Admin Queue | ||
- See description below | ||
- Interrupts | ||
- See supported interrupts below | ||
|
||
Registers | ||
--------- | ||
All registers are MMIO and big endian. | ||
|
||
The registers are used for initializing and configuring the device as well as | ||
querying device status in response to management interrupts. | ||
|
||
Admin Queue (AQ) | ||
---------------- | ||
The Admin Queue is a PAGE_SIZE memory block, treated as an array of AQ | ||
commands, used by the driver to issue commands to the device and set up | ||
resources.The driver and the device maintain a count of how many commands | ||
have been submitted and executed. To issue AQ commands, the driver must do | ||
the following (with proper locking): | ||
|
||
1) Copy new commands into next available slots in the AQ array | ||
2) Increment its counter by he number of new commands | ||
3) Write the counter into the GVE_ADMIN_QUEUE_DOORBELL register | ||
4) Poll the ADMIN_QUEUE_EVENT_COUNTER register until it equals | ||
the value written to the doorbell, or until a timeout. | ||
|
||
The device will update the status field in each AQ command reported as | ||
executed through the ADMIN_QUEUE_EVENT_COUNTER register. | ||
|
||
Interrupts | ||
---------- | ||
The following interrupts are supported by the driver: | ||
|
||
Management Interrupt | ||
~~~~~~~~~~~~~~~~~~~~ | ||
The management interrupt is used by the device to tell the driver to | ||
look at the GVE_DEVICE_STATUS register. | ||
|
||
Notification Block Interrupts | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
The notification block interrupts are used to tell the driver to poll | ||
the queues associated with that interrupt. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,7 @@ Contents: | |
intel/i40e | ||
intel/iavf | ||
intel/ice | ||
google/gve | ||
mellanox/mlx5 | ||
|
||
.. only:: subproject | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# | ||
# Google network device configuration | ||
# | ||
|
||
config NET_VENDOR_GOOGLE | ||
bool "Google Devices" | ||
default y | ||
help | ||
If you have a network (Ethernet) device belonging to this class, say Y. | ||
|
||
Note that the answer to this question doesn't directly affect the | ||
kernel: saying N will just cause the configurator to skip all | ||
the questions about Google devices. If you say Y, you will be asked | ||
for your specific device in the following questions. | ||
|
||
if NET_VENDOR_GOOGLE | ||
|
||
config GVE | ||
tristate "Google Virtual NIC (gVNIC) support" | ||
depends on PCI_MSI | ||
help | ||
This driver supports Google Virtual NIC (gVNIC)" | ||
|
||
To compile this driver as a module, choose M here. | ||
The module will be called gve. | ||
|
||
endif #NET_VENDOR_GOOGLE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# | ||
# Makefile for the Google network device drivers. | ||
# | ||
|
||
obj-$(CONFIG_GVE) += gve/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Makefile for the Google virtual Ethernet (gve) driver | ||
|
||
obj-$(CONFIG_GVE) += gve.o | ||
gve-objs := gve_main.o gve_adminq.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
/* SPDX-License-Identifier: (GPL-2.0 OR MIT) | ||
* Google virtual Ethernet (gve) driver | ||
* | ||
* Copyright (C) 2015-2019 Google, Inc. | ||
*/ | ||
|
||
#ifndef _GVE_H_ | ||
#define _GVE_H_ | ||
|
||
#include <linux/dma-mapping.h> | ||
#include <linux/netdevice.h> | ||
#include <linux/pci.h> | ||
|
||
#ifndef PCI_VENDOR_ID_GOOGLE | ||
#define PCI_VENDOR_ID_GOOGLE 0x1ae0 | ||
#endif | ||
|
||
#define PCI_DEV_ID_GVNIC 0x0042 | ||
|
||
#define GVE_REGISTER_BAR 0 | ||
#define GVE_DOORBELL_BAR 2 | ||
|
||
/* 1 for management */ | ||
#define GVE_MIN_MSIX 3 | ||
|
||
struct gve_notify_block { | ||
__be32 irq_db_index; /* idx into Bar2 - set by device, must be 1st */ | ||
char name[IFNAMSIZ + 16]; /* name registered with the kernel */ | ||
struct napi_struct napi; /* kernel napi struct for this block */ | ||
struct gve_priv *priv; | ||
} ____cacheline_aligned; | ||
|
||
struct gve_priv { | ||
struct net_device *dev; | ||
struct gve_notify_block *ntfy_blocks; /* array of num_ntfy_blks */ | ||
dma_addr_t ntfy_block_bus; | ||
struct msix_entry *msix_vectors; /* array of num_ntfy_blks + 1 */ | ||
char mgmt_msix_name[IFNAMSIZ + 16]; | ||
u32 mgmt_msix_idx; | ||
__be32 *counter_array; /* array of num_event_counters */ | ||
dma_addr_t counter_array_bus; | ||
|
||
u16 num_event_counters; | ||
|
||
u32 num_ntfy_blks; /* spilt between TX and RX so must be even */ | ||
|
||
struct gve_registers __iomem *reg_bar0; /* see gve_register.h */ | ||
__be32 __iomem *db_bar2; /* "array" of doorbells */ | ||
u32 msg_enable; /* level for netif* netdev print macros */ | ||
struct pci_dev *pdev; | ||
|
||
/* Admin queue - see gve_adminq.h*/ | ||
union gve_adminq_command *adminq; | ||
dma_addr_t adminq_bus_addr; | ||
u32 adminq_mask; /* masks prod_cnt to adminq size */ | ||
u32 adminq_prod_cnt; /* free-running count of AQ cmds executed */ | ||
|
||
unsigned long state_flags; | ||
}; | ||
|
||
enum gve_state_flags { | ||
GVE_PRIV_FLAGS_ADMIN_QUEUE_OK = BIT(1), | ||
GVE_PRIV_FLAGS_DEVICE_RESOURCES_OK = BIT(2), | ||
GVE_PRIV_FLAGS_DEVICE_RINGS_OK = BIT(3), | ||
GVE_PRIV_FLAGS_NAPI_ENABLED = BIT(4), | ||
}; | ||
|
||
static inline bool gve_get_admin_queue_ok(struct gve_priv *priv) | ||
{ | ||
return test_bit(GVE_PRIV_FLAGS_ADMIN_QUEUE_OK, &priv->state_flags); | ||
} | ||
|
||
static inline void gve_set_admin_queue_ok(struct gve_priv *priv) | ||
{ | ||
set_bit(GVE_PRIV_FLAGS_ADMIN_QUEUE_OK, &priv->state_flags); | ||
} | ||
|
||
static inline void gve_clear_admin_queue_ok(struct gve_priv *priv) | ||
{ | ||
clear_bit(GVE_PRIV_FLAGS_ADMIN_QUEUE_OK, &priv->state_flags); | ||
} | ||
|
||
static inline bool gve_get_device_resources_ok(struct gve_priv *priv) | ||
{ | ||
return test_bit(GVE_PRIV_FLAGS_DEVICE_RESOURCES_OK, &priv->state_flags); | ||
} | ||
|
||
static inline void gve_set_device_resources_ok(struct gve_priv *priv) | ||
{ | ||
set_bit(GVE_PRIV_FLAGS_DEVICE_RESOURCES_OK, &priv->state_flags); | ||
} | ||
|
||
static inline void gve_clear_device_resources_ok(struct gve_priv *priv) | ||
{ | ||
clear_bit(GVE_PRIV_FLAGS_DEVICE_RESOURCES_OK, &priv->state_flags); | ||
} | ||
|
||
static inline bool gve_get_device_rings_ok(struct gve_priv *priv) | ||
{ | ||
return test_bit(GVE_PRIV_FLAGS_DEVICE_RINGS_OK, &priv->state_flags); | ||
} | ||
|
||
static inline void gve_set_device_rings_ok(struct gve_priv *priv) | ||
{ | ||
set_bit(GVE_PRIV_FLAGS_DEVICE_RINGS_OK, &priv->state_flags); | ||
} | ||
|
||
static inline void gve_clear_device_rings_ok(struct gve_priv *priv) | ||
{ | ||
clear_bit(GVE_PRIV_FLAGS_DEVICE_RINGS_OK, &priv->state_flags); | ||
} | ||
|
||
static inline bool gve_get_napi_enabled(struct gve_priv *priv) | ||
{ | ||
return test_bit(GVE_PRIV_FLAGS_NAPI_ENABLED, &priv->state_flags); | ||
} | ||
|
||
static inline void gve_set_napi_enabled(struct gve_priv *priv) | ||
{ | ||
set_bit(GVE_PRIV_FLAGS_NAPI_ENABLED, &priv->state_flags); | ||
} | ||
|
||
static inline void gve_clear_napi_enabled(struct gve_priv *priv) | ||
{ | ||
clear_bit(GVE_PRIV_FLAGS_NAPI_ENABLED, &priv->state_flags); | ||
} | ||
|
||
/* Returns the address of the ntfy_blocks irq doorbell | ||
*/ | ||
static inline __be32 __iomem *gve_irq_doorbell(struct gve_priv *priv, | ||
struct gve_notify_block *block) | ||
{ | ||
return &priv->db_bar2[be32_to_cpu(block->irq_db_index)]; | ||
} | ||
#endif /* _GVE_H_ */ |
Oops, something went wrong.