X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fvirtio%2Fvirtio_pci.h;h=18caebdd75ca2189487a65b84d3d67636deea519;hb=112891cd27e59f8149bc4a6512dd8914dc85aa3a;hp=64d9c34642cd78f79350e294ac4fceffef7ea77f;hpb=6c3169a3dc041cbdbef506f19e3779940caa4b29;p=dpdk.git diff --git a/drivers/net/virtio/virtio_pci.h b/drivers/net/virtio/virtio_pci.h index 64d9c34642..18caebdd75 100644 --- a/drivers/net/virtio/virtio_pci.h +++ b/drivers/net/virtio/virtio_pci.h @@ -36,21 +36,16 @@ #include -#ifdef __FreeBSD__ -#include -#include -#else -#include -#endif - +#include #include struct virtqueue; +struct virtnet_ctl; /* VirtIO PCI vendor/device ID. */ #define VIRTIO_PCI_VENDORID 0x1AF4 -#define VIRTIO_PCI_DEVICEID_MIN 0x1000 -#define VIRTIO_PCI_DEVICEID_MAX 0x103F +#define VIRTIO_PCI_LEGACY_DEVICEID_NET 0x1000 +#define VIRTIO_PCI_MODERN_DEVICEID_NET 0x1041 /* VirtIO ABI version, this must match exactly. */ #define VIRTIO_PCI_ABI_VERSION 0 @@ -93,28 +88,9 @@ struct virtqueue; #define VIRTIO_CONFIG_STATUS_ACK 0x01 #define VIRTIO_CONFIG_STATUS_DRIVER 0x02 #define VIRTIO_CONFIG_STATUS_DRIVER_OK 0x04 +#define VIRTIO_CONFIG_STATUS_FEATURES_OK 0x08 #define VIRTIO_CONFIG_STATUS_FAILED 0x80 -/* - * Generate interrupt when the virtqueue ring is - * completely used, even if we've suppressed them. - */ -#define VIRTIO_F_NOTIFY_ON_EMPTY (1 << 24) - -/* - * The guest should never negotiate this feature; it - * is used to detect faulty drivers. - */ -#define VIRTIO_F_BAD_FEATURE (1 << 30) - -/* - * Some VirtIO feature bits (currently bits 28 through 31) are - * reserved for the transport being used (eg. virtio_ring), the - * rest are per-device feature bits. - */ -#define VIRTIO_TRANSPORT_F_START 28 -#define VIRTIO_TRANSPORT_F_END 32 - /* * Each virtqueue indirect descriptor list must be physically contiguous. * To allow us to malloc(9) each list individually, limit the number @@ -128,52 +104,191 @@ struct virtqueue; #define VIRTIO_MAX_INDIRECT ((int) (PAGE_SIZE / 16)) /* The feature bitmap for virtio net */ -#define VIRTIO_NET_F_CSUM 0x00001 /* Host handles pkts w/ partial csum */ -#define VIRTIO_NET_F_GUEST_CSUM 0x00002 /* Guest handles pkts w/ partial csum*/ -#define VIRTIO_NET_F_MAC 0x00020 /* Host has given MAC address. */ -#define VIRTIO_NET_F_GSO 0x00040 /* Host handles pkts w/ any GSO type */ -#define VIRTIO_NET_F_GUEST_TSO4 0x00080 /* Guest can handle TSOv4 in. */ -#define VIRTIO_NET_F_GUEST_TSO6 0x00100 /* Guest can handle TSOv6 in. */ -#define VIRTIO_NET_F_GUEST_ECN 0x00200 /* Guest can handle TSO[6] w/ ECN in.*/ -#define VIRTIO_NET_F_GUEST_UFO 0x00400 /* Guest can handle UFO in. */ -#define VIRTIO_NET_F_HOST_TSO4 0x00800 /* Host can handle TSOv4 in. */ -#define VIRTIO_NET_F_HOST_TSO6 0x01000 /* Host can handle TSOv6 in. */ -#define VIRTIO_NET_F_HOST_ECN 0x02000 /* Host can handle TSO[6] w/ ECN in. */ -#define VIRTIO_NET_F_HOST_UFO 0x04000 /* Host can handle UFO in. */ -#define VIRTIO_NET_F_MRG_RXBUF 0x08000 /* Host can merge receive buffers. */ -#define VIRTIO_NET_F_STATUS 0x10000 /* virtio_net_config.status available*/ -#define VIRTIO_NET_F_CTRL_VQ 0x20000 /* Control channel available */ -#define VIRTIO_NET_F_CTRL_RX 0x40000 /* Control channel RX mode support */ -#define VIRTIO_NET_F_CTRL_VLAN 0x80000 /* Control channel VLAN filtering */ -#define VIRTIO_NET_F_CTRL_RX_EXTRA 0x100000 /* Extra RX mode control support */ -#define VIRTIO_RING_F_INDIRECT_DESC 0x10000000 /* Support for indirect buffer descriptors. */ -/* The guest publishes the used index for which it expects an interrupt - * at the end of the avail ring. Host should ignore the avail->flags field. - * The host publishes the avail index for which it expects a kick - * at the end of the used ring. Guest should ignore the used->flags field. +#define VIRTIO_NET_F_CSUM 0 /* Host handles pkts w/ partial csum */ +#define VIRTIO_NET_F_GUEST_CSUM 1 /* Guest handles pkts w/ partial csum */ +#define VIRTIO_NET_F_MTU 3 /* Initial MTU advice. */ +#define VIRTIO_NET_F_MAC 5 /* Host has given MAC address. */ +#define VIRTIO_NET_F_GUEST_TSO4 7 /* Guest can handle TSOv4 in. */ +#define VIRTIO_NET_F_GUEST_TSO6 8 /* Guest can handle TSOv6 in. */ +#define VIRTIO_NET_F_GUEST_ECN 9 /* Guest can handle TSO[6] w/ ECN in. */ +#define VIRTIO_NET_F_GUEST_UFO 10 /* Guest can handle UFO in. */ +#define VIRTIO_NET_F_HOST_TSO4 11 /* Host can handle TSOv4 in. */ +#define VIRTIO_NET_F_HOST_TSO6 12 /* Host can handle TSOv6 in. */ +#define VIRTIO_NET_F_HOST_ECN 13 /* Host can handle TSO[6] w/ ECN in. */ +#define VIRTIO_NET_F_HOST_UFO 14 /* Host can handle UFO in. */ +#define VIRTIO_NET_F_MRG_RXBUF 15 /* Host can merge receive buffers. */ +#define VIRTIO_NET_F_STATUS 16 /* virtio_net_config.status available */ +#define VIRTIO_NET_F_CTRL_VQ 17 /* Control channel available */ +#define VIRTIO_NET_F_CTRL_RX 18 /* Control channel RX mode support */ +#define VIRTIO_NET_F_CTRL_VLAN 19 /* Control channel VLAN filtering */ +#define VIRTIO_NET_F_CTRL_RX_EXTRA 20 /* Extra RX mode control support */ +#define VIRTIO_NET_F_GUEST_ANNOUNCE 21 /* Guest can announce device on the + * network */ +#define VIRTIO_NET_F_MQ 22 /* Device supports Receive Flow + * Steering */ +#define VIRTIO_NET_F_CTRL_MAC_ADDR 23 /* Set MAC address */ + +/* Do we get callbacks when the ring is completely used, even if we've + * suppressed them? */ +#define VIRTIO_F_NOTIFY_ON_EMPTY 24 + +/* Can the device handle any descriptor layout? */ +#define VIRTIO_F_ANY_LAYOUT 27 + +/* We support indirect buffer descriptors */ +#define VIRTIO_RING_F_INDIRECT_DESC 28 + +#define VIRTIO_F_VERSION_1 32 +#define VIRTIO_F_IOMMU_PLATFORM 33 + +/* + * Some VirtIO feature bits (currently bits 28 through 31) are + * reserved for the transport being used (eg. virtio_ring), the + * rest are per-device feature bits. */ -#define VIRTIO_RING_F_EVENT_IDX 0x20000000 +#define VIRTIO_TRANSPORT_F_START 28 +#define VIRTIO_TRANSPORT_F_END 34 -#define VIRTIO_NET_S_LINK_UP 1 /* Link is up */ +/* The Guest publishes the used index for which it expects an interrupt + * at the end of the avail ring. Host should ignore the avail->flags field. */ +/* The Host publishes the avail index for which it expects a kick + * at the end of the used ring. Guest should ignore the used->flags field. */ +#define VIRTIO_RING_F_EVENT_IDX 29 + +#define VIRTIO_NET_S_LINK_UP 1 /* Link is up */ +#define VIRTIO_NET_S_ANNOUNCE 2 /* Announcement is needed */ /* * Maximum number of virtqueues per device. */ -#define VIRTIO_MAX_VIRTQUEUES 8 +#define VIRTIO_MAX_VIRTQUEUE_PAIRS 8 +#define VIRTIO_MAX_VIRTQUEUES (VIRTIO_MAX_VIRTQUEUE_PAIRS * 2 + 1) + +/* Common configuration */ +#define VIRTIO_PCI_CAP_COMMON_CFG 1 +/* Notifications */ +#define VIRTIO_PCI_CAP_NOTIFY_CFG 2 +/* ISR Status */ +#define VIRTIO_PCI_CAP_ISR_CFG 3 +/* Device specific configuration */ +#define VIRTIO_PCI_CAP_DEVICE_CFG 4 +/* PCI configuration access */ +#define VIRTIO_PCI_CAP_PCI_CFG 5 + +/* This is the PCI capability header: */ +struct virtio_pci_cap { + uint8_t cap_vndr; /* Generic PCI field: PCI_CAP_ID_VNDR */ + uint8_t cap_next; /* Generic PCI field: next ptr. */ + uint8_t cap_len; /* Generic PCI field: capability length */ + uint8_t cfg_type; /* Identifies the structure. */ + uint8_t bar; /* Where to find it. */ + uint8_t padding[3]; /* Pad to full dword. */ + uint32_t offset; /* Offset within bar. */ + uint32_t length; /* Length of the structure, in bytes. */ +}; + +struct virtio_pci_notify_cap { + struct virtio_pci_cap cap; + uint32_t notify_off_multiplier; /* Multiplier for queue_notify_off. */ +}; + +/* Fields in VIRTIO_PCI_CAP_COMMON_CFG: */ +struct virtio_pci_common_cfg { + /* About the whole device. */ + uint32_t device_feature_select; /* read-write */ + uint32_t device_feature; /* read-only */ + uint32_t guest_feature_select; /* read-write */ + uint32_t guest_feature; /* read-write */ + uint16_t msix_config; /* read-write */ + uint16_t num_queues; /* read-only */ + uint8_t device_status; /* read-write */ + uint8_t config_generation; /* read-only */ + + /* About a specific virtqueue. */ + uint16_t queue_select; /* read-write */ + uint16_t queue_size; /* read-write, power of 2. */ + uint16_t queue_msix_vector; /* read-write */ + uint16_t queue_enable; /* read-write */ + uint16_t queue_notify_off; /* read-only */ + uint32_t queue_desc_lo; /* read-write */ + uint32_t queue_desc_hi; /* read-write */ + uint32_t queue_avail_lo; /* read-write */ + uint32_t queue_avail_hi; /* read-write */ + uint32_t queue_used_lo; /* read-write */ + uint32_t queue_used_hi; /* read-write */ +}; + +struct virtio_hw; + +struct virtio_pci_ops { + void (*read_dev_cfg)(struct virtio_hw *hw, size_t offset, + void *dst, int len); + void (*write_dev_cfg)(struct virtio_hw *hw, size_t offset, + const void *src, int len); + void (*reset)(struct virtio_hw *hw); + + uint8_t (*get_status)(struct virtio_hw *hw); + void (*set_status)(struct virtio_hw *hw, uint8_t status); + + uint64_t (*get_features)(struct virtio_hw *hw); + void (*set_features)(struct virtio_hw *hw, uint64_t features); + + uint8_t (*get_isr)(struct virtio_hw *hw); + + uint16_t (*set_config_irq)(struct virtio_hw *hw, uint16_t vec); + + uint16_t (*set_queue_irq)(struct virtio_hw *hw, struct virtqueue *vq, + uint16_t vec); + + uint16_t (*get_queue_num)(struct virtio_hw *hw, uint16_t queue_id); + int (*setup_queue)(struct virtio_hw *hw, struct virtqueue *vq); + void (*del_queue)(struct virtio_hw *hw, struct virtqueue *vq); + void (*notify_queue)(struct virtio_hw *hw, struct virtqueue *vq); +}; + +struct virtio_net_config; struct virtio_hw { - struct virtqueue *cvq; - uint32_t io_base; - uint32_t guest_features; - uint32_t max_tx_queues; - uint32_t max_rx_queues; + struct virtnet_ctl *cvq; + uint64_t req_guest_features; + uint64_t guest_features; + uint32_t max_queue_pairs; + uint16_t started; + uint16_t max_mtu; uint16_t vtnet_hdr_size; uint8_t vlan_strip; uint8_t use_msix; - uint8_t started; + uint8_t modern; + uint8_t use_simple_rxtx; + uint8_t port_id; uint8_t mac_addr[ETHER_ADDR_LEN]; + uint32_t notify_off_multiplier; + uint8_t *isr; + uint16_t *notify_base; + struct virtio_pci_common_cfg *common_cfg; + struct virtio_net_config *dev_cfg; + void *virtio_user_dev; + + struct virtqueue **vqs; +}; + + +/* + * While virtio_hw is stored in shared memory, this structure stores + * some infos that may vary in the multiple process model locally. + * For example, the vtpci_ops pointer. + */ +struct virtio_hw_internal { + const struct virtio_pci_ops *vtpci_ops; + struct rte_pci_ioport io; }; +#define VTPCI_OPS(hw) (virtio_hw_internal[(hw)->port_id].vtpci_ops) +#define VTPCI_IO(hw) (&virtio_hw_internal[(hw)->port_id].io) + +extern struct virtio_hw_internal virtio_hw_internal[RTE_MAX_ETHPORTS]; + + /* * This structure is just a reference to read * net device specific config space; it just a chodu structure @@ -185,14 +300,9 @@ struct virtio_net_config { /* See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above */ uint16_t status; uint16_t max_virtqueue_pairs; + uint16_t mtu; } __attribute__((packed)); -/* - * The remaining space is defined by each driver as the per-driver - * configuration space. - */ -#define VIRTIO_PCI_CONFIG(hw) (((hw)->use_msix) ? 24 : 20) - /* * How many bits to shift physical queue address written to QUEUE_PFN. * 12 is historical, and due to x86 page size. @@ -202,69 +312,33 @@ struct virtio_net_config { /* The alignment to use between consumer and producer parts of vring. */ #define VIRTIO_PCI_VRING_ALIGN 4096 -#ifdef __FreeBSD__ - -static inline void -outb_p(unsigned char data, unsigned int port) -{ - - outb(port, (u_char)data); -} - -static inline void -outw_p(unsigned short data, unsigned int port) -{ - outw(port, (u_short)data); -} - -static inline void -outl_p(unsigned int data, unsigned int port) -{ - outl(port, (u_int)data); -} -#endif - -#define VIRTIO_PCI_REG_ADDR(hw, reg) \ - (unsigned short)((hw)->io_base + (reg)) - -#define VIRTIO_READ_REG_1(hw, reg) \ - inb((VIRTIO_PCI_REG_ADDR((hw), (reg)))) -#define VIRTIO_WRITE_REG_1(hw, reg, value) \ - outb_p((unsigned char)(value), (VIRTIO_PCI_REG_ADDR((hw), (reg)))) - -#define VIRTIO_READ_REG_2(hw, reg) \ - inw((VIRTIO_PCI_REG_ADDR((hw), (reg)))) -#define VIRTIO_WRITE_REG_2(hw, reg, value) \ - outw_p((unsigned short)(value), (VIRTIO_PCI_REG_ADDR((hw), (reg)))) - -#define VIRTIO_READ_REG_4(hw, reg) \ - inl((VIRTIO_PCI_REG_ADDR((hw), (reg)))) -#define VIRTIO_WRITE_REG_4(hw, reg, value) \ - outl_p((unsigned int)(value), (VIRTIO_PCI_REG_ADDR((hw), (reg)))) - static inline int -vtpci_with_feature(struct virtio_hw *hw, uint32_t feature) +vtpci_with_feature(struct virtio_hw *hw, uint64_t bit) { - return (hw->guest_features & feature) != 0; + return (hw->guest_features & (1ULL << bit)) != 0; } /* * Function declaration from virtio_pci.c */ +int vtpci_init(struct rte_pci_device *dev, struct virtio_hw *hw); void vtpci_reset(struct virtio_hw *); void vtpci_reinit_complete(struct virtio_hw *); +uint8_t vtpci_get_status(struct virtio_hw *); void vtpci_set_status(struct virtio_hw *, uint8_t); -uint32_t vtpci_negotiate_features(struct virtio_hw *, uint32_t); +uint64_t vtpci_negotiate_features(struct virtio_hw *, uint64_t); -void vtpci_write_dev_config(struct virtio_hw *, uint64_t, void *, int); +void vtpci_write_dev_config(struct virtio_hw *, size_t, const void *, int); -void vtpci_read_dev_config(struct virtio_hw *, uint64_t, void *, int); +void vtpci_read_dev_config(struct virtio_hw *, size_t, void *, int); uint8_t vtpci_isr(struct virtio_hw *); -uint16_t vtpci_irq_config(struct virtio_hw *, uint16_t); +extern const struct virtio_pci_ops legacy_ops; +extern const struct virtio_pci_ops modern_ops; +extern const struct virtio_pci_ops virtio_user_ops; #endif /* _VIRTIO_PCI_H_ */