diff options
author | Wei Liu <wei.liu2@citrix.com> | 2013-08-26 07:59:38 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-08-29 01:18:04 -0400 |
commit | b3f980bd827e6e81a050c518d60ed7811a83061d (patch) | |
tree | 2104c030c277c9eab340ab424fa669562fc0189a /drivers/net/xen-netback/common.h | |
parent | 43e9d1943278e96150b449ea1fa81f4ae27729d5 (diff) |
xen-netback: switch to NAPI + kthread 1:1 model
This patch implements 1:1 model netback. NAPI and kthread are utilized
to do the weight-lifting job:
- NAPI is used for guest side TX (host side RX)
- kthread is used for guest side RX (host side TX)
Xenvif and xen_netbk are made into one structure to reduce code size.
This model provides better scheduling fairness among vifs. It is also
prerequisite for implementing multiqueue for Xen netback.
Signed-off-by: Wei Liu <wei.liu2@citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/xen-netback/common.h')
-rw-r--r-- | drivers/net/xen-netback/common.h | 132 |
1 files changed, 94 insertions, 38 deletions
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 8a4d77ee9c5b..9c1f15872e17 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h | |||
@@ -45,31 +45,109 @@ | |||
45 | #include <xen/grant_table.h> | 45 | #include <xen/grant_table.h> |
46 | #include <xen/xenbus.h> | 46 | #include <xen/xenbus.h> |
47 | 47 | ||
48 | struct xen_netbk; | 48 | typedef unsigned int pending_ring_idx_t; |
49 | #define INVALID_PENDING_RING_IDX (~0U) | ||
50 | |||
51 | /* For the head field in pending_tx_info: it is used to indicate | ||
52 | * whether this tx info is the head of one or more coalesced requests. | ||
53 | * | ||
54 | * When head != INVALID_PENDING_RING_IDX, it means the start of a new | ||
55 | * tx requests queue and the end of previous queue. | ||
56 | * | ||
57 | * An example sequence of head fields (I = INVALID_PENDING_RING_IDX): | ||
58 | * | ||
59 | * ...|0 I I I|5 I|9 I I I|... | ||
60 | * -->|<-INUSE---------------- | ||
61 | * | ||
62 | * After consuming the first slot(s) we have: | ||
63 | * | ||
64 | * ...|V V V V|5 I|9 I I I|... | ||
65 | * -----FREE->|<-INUSE-------- | ||
66 | * | ||
67 | * where V stands for "valid pending ring index". Any number other | ||
68 | * than INVALID_PENDING_RING_IDX is OK. These entries are considered | ||
69 | * free and can contain any number other than | ||
70 | * INVALID_PENDING_RING_IDX. In practice we use 0. | ||
71 | * | ||
72 | * The in use non-INVALID_PENDING_RING_IDX (say 0, 5 and 9 in the | ||
73 | * above example) number is the index into pending_tx_info and | ||
74 | * mmap_pages arrays. | ||
75 | */ | ||
76 | struct pending_tx_info { | ||
77 | struct xen_netif_tx_request req; /* coalesced tx request */ | ||
78 | pending_ring_idx_t head; /* head != INVALID_PENDING_RING_IDX | ||
79 | * if it is head of one or more tx | ||
80 | * reqs | ||
81 | */ | ||
82 | }; | ||
83 | |||
84 | #define XEN_NETIF_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, PAGE_SIZE) | ||
85 | #define XEN_NETIF_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, PAGE_SIZE) | ||
86 | |||
87 | struct xenvif_rx_meta { | ||
88 | int id; | ||
89 | int size; | ||
90 | int gso_size; | ||
91 | }; | ||
92 | |||
93 | /* Discriminate from any valid pending_idx value. */ | ||
94 | #define INVALID_PENDING_IDX 0xFFFF | ||
95 | |||
96 | #define MAX_BUFFER_OFFSET PAGE_SIZE | ||
97 | |||
98 | #define MAX_PENDING_REQS 256 | ||
49 | 99 | ||
50 | struct xenvif { | 100 | struct xenvif { |
51 | /* Unique identifier for this interface. */ | 101 | /* Unique identifier for this interface. */ |
52 | domid_t domid; | 102 | domid_t domid; |
53 | unsigned int handle; | 103 | unsigned int handle; |
54 | 104 | ||
55 | /* Reference to netback processing backend. */ | 105 | /* Use NAPI for guest TX */ |
56 | struct xen_netbk *netbk; | 106 | struct napi_struct napi; |
107 | /* When feature-split-event-channels = 0, tx_irq = rx_irq. */ | ||
108 | unsigned int tx_irq; | ||
109 | /* Only used when feature-split-event-channels = 1 */ | ||
110 | char tx_irq_name[IFNAMSIZ+4]; /* DEVNAME-tx */ | ||
111 | struct xen_netif_tx_back_ring tx; | ||
112 | struct sk_buff_head tx_queue; | ||
113 | struct page *mmap_pages[MAX_PENDING_REQS]; | ||
114 | pending_ring_idx_t pending_prod; | ||
115 | pending_ring_idx_t pending_cons; | ||
116 | u16 pending_ring[MAX_PENDING_REQS]; | ||
117 | struct pending_tx_info pending_tx_info[MAX_PENDING_REQS]; | ||
118 | |||
119 | /* Coalescing tx requests before copying makes number of grant | ||
120 | * copy ops greater or equal to number of slots required. In | ||
121 | * worst case a tx request consumes 2 gnttab_copy. | ||
122 | */ | ||
123 | struct gnttab_copy tx_copy_ops[2*MAX_PENDING_REQS]; | ||
57 | 124 | ||
58 | u8 fe_dev_addr[6]; | ||
59 | 125 | ||
126 | /* Use kthread for guest RX */ | ||
127 | struct task_struct *task; | ||
128 | wait_queue_head_t wq; | ||
60 | /* When feature-split-event-channels = 0, tx_irq = rx_irq. */ | 129 | /* When feature-split-event-channels = 0, tx_irq = rx_irq. */ |
61 | unsigned int tx_irq; | ||
62 | unsigned int rx_irq; | 130 | unsigned int rx_irq; |
63 | /* Only used when feature-split-event-channels = 1 */ | 131 | /* Only used when feature-split-event-channels = 1 */ |
64 | char tx_irq_name[IFNAMSIZ+4]; /* DEVNAME-tx */ | ||
65 | char rx_irq_name[IFNAMSIZ+4]; /* DEVNAME-rx */ | 132 | char rx_irq_name[IFNAMSIZ+4]; /* DEVNAME-rx */ |
133 | struct xen_netif_rx_back_ring rx; | ||
134 | struct sk_buff_head rx_queue; | ||
66 | 135 | ||
67 | /* List of frontends to notify after a batch of frames sent. */ | 136 | /* Allow xenvif_start_xmit() to peek ahead in the rx request |
68 | struct list_head notify_list; | 137 | * ring. This is a prediction of what rx_req_cons will be |
138 | * once all queued skbs are put on the ring. | ||
139 | */ | ||
140 | RING_IDX rx_req_cons_peek; | ||
141 | |||
142 | /* Given MAX_BUFFER_OFFSET of 4096 the worst case is that each | ||
143 | * head/fragment page uses 2 copy operations because it | ||
144 | * straddles two buffers in the frontend. | ||
145 | */ | ||
146 | struct gnttab_copy grant_copy_op[2*XEN_NETIF_RX_RING_SIZE]; | ||
147 | struct xenvif_rx_meta meta[2*XEN_NETIF_RX_RING_SIZE]; | ||
69 | 148 | ||
70 | /* The shared rings and indexes. */ | 149 | |
71 | struct xen_netif_tx_back_ring tx; | 150 | u8 fe_dev_addr[6]; |
72 | struct xen_netif_rx_back_ring rx; | ||
73 | 151 | ||
74 | /* Frontend feature information. */ | 152 | /* Frontend feature information. */ |
75 | u8 can_sg:1; | 153 | u8 can_sg:1; |
@@ -80,13 +158,6 @@ struct xenvif { | |||
80 | /* Internal feature information. */ | 158 | /* Internal feature information. */ |
81 | u8 can_queue:1; /* can queue packets for receiver? */ | 159 | u8 can_queue:1; /* can queue packets for receiver? */ |
82 | 160 | ||
83 | /* | ||
84 | * Allow xenvif_start_xmit() to peek ahead in the rx request | ||
85 | * ring. This is a prediction of what rx_req_cons will be | ||
86 | * once all queued skbs are put on the ring. | ||
87 | */ | ||
88 | RING_IDX rx_req_cons_peek; | ||
89 | |||
90 | /* Transmit shaping: allow 'credit_bytes' every 'credit_usec'. */ | 161 | /* Transmit shaping: allow 'credit_bytes' every 'credit_usec'. */ |
91 | unsigned long credit_bytes; | 162 | unsigned long credit_bytes; |
92 | unsigned long credit_usec; | 163 | unsigned long credit_usec; |
@@ -97,11 +168,7 @@ struct xenvif { | |||
97 | unsigned long rx_gso_checksum_fixup; | 168 | unsigned long rx_gso_checksum_fixup; |
98 | 169 | ||
99 | /* Miscellaneous private stuff. */ | 170 | /* Miscellaneous private stuff. */ |
100 | struct list_head schedule_list; | ||
101 | atomic_t refcnt; | ||
102 | struct net_device *dev; | 171 | struct net_device *dev; |
103 | |||
104 | wait_queue_head_t waiting_to_free; | ||
105 | }; | 172 | }; |
106 | 173 | ||
107 | static inline struct xenbus_device *xenvif_to_xenbus_device(struct xenvif *vif) | 174 | static inline struct xenbus_device *xenvif_to_xenbus_device(struct xenvif *vif) |
@@ -109,9 +176,6 @@ static inline struct xenbus_device *xenvif_to_xenbus_device(struct xenvif *vif) | |||
109 | return to_xenbus_device(vif->dev->dev.parent); | 176 | return to_xenbus_device(vif->dev->dev.parent); |
110 | } | 177 | } |
111 | 178 | ||
112 | #define XEN_NETIF_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, PAGE_SIZE) | ||
113 | #define XEN_NETIF_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, PAGE_SIZE) | ||
114 | |||
115 | struct xenvif *xenvif_alloc(struct device *parent, | 179 | struct xenvif *xenvif_alloc(struct device *parent, |
116 | domid_t domid, | 180 | domid_t domid, |
117 | unsigned int handle); | 181 | unsigned int handle); |
@@ -121,9 +185,6 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref, | |||
121 | unsigned int rx_evtchn); | 185 | unsigned int rx_evtchn); |
122 | void xenvif_disconnect(struct xenvif *vif); | 186 | void xenvif_disconnect(struct xenvif *vif); |
123 | 187 | ||
124 | void xenvif_get(struct xenvif *vif); | ||
125 | void xenvif_put(struct xenvif *vif); | ||
126 | |||
127 | int xenvif_xenbus_init(void); | 188 | int xenvif_xenbus_init(void); |
128 | void xenvif_xenbus_fini(void); | 189 | void xenvif_xenbus_fini(void); |
129 | 190 | ||
@@ -139,18 +200,8 @@ int xen_netbk_map_frontend_rings(struct xenvif *vif, | |||
139 | grant_ref_t tx_ring_ref, | 200 | grant_ref_t tx_ring_ref, |
140 | grant_ref_t rx_ring_ref); | 201 | grant_ref_t rx_ring_ref); |
141 | 202 | ||
142 | /* (De)Register a xenvif with the netback backend. */ | ||
143 | void xen_netbk_add_xenvif(struct xenvif *vif); | ||
144 | void xen_netbk_remove_xenvif(struct xenvif *vif); | ||
145 | |||
146 | /* (De)Schedule backend processing for a xenvif */ | ||
147 | void xen_netbk_schedule_xenvif(struct xenvif *vif); | ||
148 | void xen_netbk_deschedule_xenvif(struct xenvif *vif); | ||
149 | |||
150 | /* Check for SKBs from frontend and schedule backend processing */ | 203 | /* Check for SKBs from frontend and schedule backend processing */ |
151 | void xen_netbk_check_rx_xenvif(struct xenvif *vif); | 204 | void xen_netbk_check_rx_xenvif(struct xenvif *vif); |
152 | /* Receive an SKB from the frontend */ | ||
153 | void xenvif_receive_skb(struct xenvif *vif, struct sk_buff *skb); | ||
154 | 205 | ||
155 | /* Queue an SKB for transmission to the frontend */ | 206 | /* Queue an SKB for transmission to the frontend */ |
156 | void xen_netbk_queue_tx_skb(struct xenvif *vif, struct sk_buff *skb); | 207 | void xen_netbk_queue_tx_skb(struct xenvif *vif, struct sk_buff *skb); |
@@ -163,6 +214,11 @@ void xenvif_carrier_off(struct xenvif *vif); | |||
163 | /* Returns number of ring slots required to send an skb to the frontend */ | 214 | /* Returns number of ring slots required to send an skb to the frontend */ |
164 | unsigned int xen_netbk_count_skb_slots(struct xenvif *vif, struct sk_buff *skb); | 215 | unsigned int xen_netbk_count_skb_slots(struct xenvif *vif, struct sk_buff *skb); |
165 | 216 | ||
217 | int xen_netbk_tx_action(struct xenvif *vif, int budget); | ||
218 | void xen_netbk_rx_action(struct xenvif *vif); | ||
219 | |||
220 | int xen_netbk_kthread(void *data); | ||
221 | |||
166 | extern bool separate_tx_rx_irq; | 222 | extern bool separate_tx_rx_irq; |
167 | 223 | ||
168 | #endif /* __XEN_NETBACK__COMMON_H__ */ | 224 | #endif /* __XEN_NETBACK__COMMON_H__ */ |