Mercurial > archived > louis > epitech > mq > rathaxes
comparison e1000_implement_the_frame_transmission_chunk.patch @ 87:e9736ab70995
Add a couple of patches to the build system and WIP on the e1000 code architecture to implement the tranmission
author | Louis Opter <louis@lse.epitech.net> |
---|---|
date | Mon, 24 Sep 2012 09:13:15 +0200 |
parents | c99e69966dd3 |
children | 8ffcdd6aa410 |
comparison
equal
deleted
inserted
replaced
86:c99e69966dd3 | 87:e9736ab70995 |
---|---|
1 # HG changeset patch | 1 # HG changeset patch |
2 # Parent 42d6e2a573d077772c1a9c697cc066337569b129 | 2 # Parent 87ba2a19a59fb7be346ad40a57439b6b752b152e |
3 rathaxes: start to queue up packets in the TX ring on the e1000 sample | 3 rathaxes: start to queue up packets in the TX ring on the e1000 sample |
4 | 4 |
5 diff --git a/maintainers/CMakeScripts/Templates/MakefileLKM.in b/maintainers/CMakeScripts/Templates/MakefileLKM.in | 5 diff --git a/rathaxes/samples/e1000/CMakeLists.txt b/rathaxes/samples/e1000/CMakeLists.txt |
6 --- a/maintainers/CMakeScripts/Templates/MakefileLKM.in | 6 --- a/rathaxes/samples/e1000/CMakeLists.txt |
7 +++ b/maintainers/CMakeScripts/Templates/MakefileLKM.in | 7 +++ b/rathaxes/samples/e1000/CMakeLists.txt |
8 @@ -1,6 +1,6 @@ | 8 @@ -1,6 +1,22 @@ |
9 # Disable this "coding-style" warning (seriously, you have to compile with | 9 -ADD_RATHAXES_SOURCES(e1000_src lkm.rtx |
10 # -pedantic to get it...) | 10 - RTI builtin.rti log.rti lkm.rti pci.rti socket.rti ethernet.rti e1000.rti |
11 -EXTRA_CFLAGS = -Wno-declaration-after-statement | 11 - BLT log.blt lkm.blt pci.blt socket.blt ethernet.blt e1000.blt) |
12 +EXTRA_CFLAGS = -Wno-declaration-after-statement -std=gnu99 | 12 +ADD_RATHAXES_SOURCES(e1000_src |
13 | 13 + lkm.rtx |
14 KDIR = /lib/modules/$(shell uname -r)/build | 14 + RTI |
15 obj-m := @LKM_OBJECTS@ | 15 + builtin.rti |
16 + log.rti | |
17 + lkm.rti | |
18 + device.rti | |
19 + pci.rti | |
20 + socket.rti | |
21 + ethernet.rti | |
22 + e1000.rti | |
23 + BLT | |
24 + log.blt | |
25 + lkm.blt | |
26 + pci.blt | |
27 + device.blt | |
28 + socket.blt | |
29 + ethernet.blt | |
30 + e1000.blt) | |
31 | |
32 IF (LINUX_KBUILD_DIR) | |
33 ADD_RATHAXES_LKM(e1000 e1000_src) | |
34 diff --git a/rathaxes/samples/e1000/device.blt b/rathaxes/samples/e1000/device.blt | |
35 new file mode 100644 | |
36 --- /dev/null | |
37 +++ b/rathaxes/samples/e1000/device.blt | |
38 @@ -0,0 +1,25 @@ | |
39 +with Device, LKM | |
40 +{ | |
41 + template type Device::Device() | |
42 + { | |
43 + chunk LKM::includes() | |
44 + { | |
45 + #include <linux/device.h> | |
46 + | |
47 + static const ${Device::Device} force_rtx_device_decl; | |
48 + } | |
49 + | |
50 + chunk decl() | |
51 + { | |
52 + typedef struct device *rtx_device_p; | |
53 + } | |
54 + | |
55 + chunk init() | |
56 + { | |
57 + } | |
58 + | |
59 + map | |
60 + { | |
61 + } | |
62 + } | |
63 +} | |
64 diff --git a/rathaxes/samples/e1000/device.rti b/rathaxes/samples/e1000/device.rti | |
65 new file mode 100644 | |
66 --- /dev/null | |
67 +++ b/rathaxes/samples/e1000/device.rti | |
68 @@ -0,0 +1,9 @@ | |
69 +interface Device : LKM | |
70 +{ | |
71 + provided type Device | |
72 + { | |
73 + chunk LKM::includes(); | |
74 + method decl(); | |
75 + method init(); | |
76 + } | |
77 +} | |
16 diff --git a/rathaxes/samples/e1000/e1000.blt b/rathaxes/samples/e1000/e1000.blt | 78 diff --git a/rathaxes/samples/e1000/e1000.blt b/rathaxes/samples/e1000/e1000.blt |
17 --- a/rathaxes/samples/e1000/e1000.blt | 79 --- a/rathaxes/samples/e1000/e1000.blt |
18 +++ b/rathaxes/samples/e1000/e1000.blt | 80 +++ b/rathaxes/samples/e1000/e1000.blt |
19 @@ -332,6 +332,30 @@ | 81 @@ -110,9 +110,9 @@ |
82 { | |
83 unsigned int size; | |
84 struct rtx_e1000_rx_descriptor *base; | |
85 - void* /* dma_addr_t */ dma_base; | |
86 + dma_addr_t dma_base; | |
87 struct sk_buff *skbuffs[256 /* ${config.rx_ring_size} */]; | |
88 - void* /* dma_addr_t */ dma_skbuffs[256 /* ${config.rx_ring_size} */]; | |
89 + dma_addr_t dma_skbuffs[256 /* ${config.rx_ring_size} */]; | |
90 }; | |
91 } | |
92 | |
93 @@ -148,11 +148,59 @@ | |
94 struct rtx_e1000_tx_ring | |
95 { | |
96 unsigned int size; | |
97 + /* We should probably use ${e1000::TxDescriptor} here: */ | |
98 struct rtx_e1000_tx_descriptor *base; | |
99 - void* /* dma_addr_t */ dma_base; | |
100 + dma_addr_t dma_base; | |
101 + /* indexes on base */ | |
102 + unsigned int head; | |
103 + unsigned int tail; | |
104 }; | |
105 } | |
106 | |
107 + chunk LKM::prototypes() | |
108 + { | |
109 + static unsigned int rtx_e1000_tx_ring_descriptors_remaining(struct rtx_e1000_tx_ring *); | |
110 + static int rtx_e1000_tx_ring_tso_cksum_offload(struct rtx_e1000_tx_ring *, struct rtx_socket_skbuff *); | |
111 + static int rtx_e1000_tx_ring_put(struct rtx_e1000_tx_ring *, struct rtx_socket_skbuff *); | |
112 + } | |
113 + | |
114 + chunk LKM::code() | |
115 + { | |
116 + static unsigned int rtx_e1000_tx_ring_descriptors_remaining(struct rtx_e1000_tx_ring *self) | |
117 + { | |
118 + if (self->tail == self->head) /* ring is empty */ | |
119 + return 256; /* XXX: ${config.tx_ring_size}; */ | |
120 + if (self->tail > self->head) | |
121 + /* XXX: ${config.tx_ring_size} */ | |
122 + return 256 - (self->tail - self->head); | |
123 + return self->head - self->tail; | |
124 + } | |
125 + | |
126 + static int rtx_e1000_tx_ring_tso_cksum_offload(struct rtx_e1000_tx_ring *self, struct rtx_socket_skbuff *skb) | |
127 + { | |
128 + return skb_is_gso(skb->skbuff) || skb->skbuff->ip_summed == CHECKSUM_PARTIAL; | |
129 + } | |
130 + | |
131 + static int rtx_e1000_tx_ring_put(struct rtx_e1000_tx_ring *self, struct rtx_socket_skbuff *skb) | |
132 + { | |
133 + return NETDEV_TX_OK; | |
134 + } | |
135 + } | |
136 + | |
137 + chunk descriptors_remaining() | |
138 + { | |
139 + rtx_e1000_tx_ring_descriptors_remaining(${self}); | |
140 + } | |
141 + | |
142 + chunk tso_cksum_offload(Socket::SKBuff skb) | |
143 + { | |
144 + } | |
145 + | |
146 + chunk put(Socket::SKBuff skb) | |
147 + { | |
148 + rtx_e1000_tx_ring_put(${self}, &${skb}); | |
149 + } | |
150 + | |
151 chunk ::init() | |
152 { | |
153 } | |
154 @@ -183,7 +231,7 @@ | |
155 struct rtx_e1000_ctx | |
156 { | |
157 int bars; | |
158 - unsigned char /* __iomem */ *ioaddr; | |
159 + unsigned char __iomem *ioaddr; | |
160 int irq; | |
161 | |
162 /* we can't use the Rathaxes type here (#8) */ | |
163 @@ -334,6 +382,30 @@ | |
20 } | 164 } |
21 } | 165 } |
22 | 166 |
23 + template type e1000::TxFlags() | 167 + template type e1000::TxFlags() |
24 + { | 168 + { |
45 + } | 189 + } |
46 + | 190 + |
47 template sequence e1000::create_device() | 191 template sequence e1000::create_device() |
48 { | 192 { |
49 chunk Ethernet::create_device(PCI::Device pdev, Ethernet::Device rtx_ether_ctx) | 193 chunk Ethernet::create_device(PCI::Device pdev, Ethernet::Device rtx_ether_ctx) |
50 @@ -964,4 +988,86 @@ | 194 @@ -358,8 +430,8 @@ |
195 ${Log::info("e1000::create: pci_enable_device_mem failed")}; | |
196 if (pci_request_selected_regions(${pdev}, ${rtx_ether_ctx}->hw_ctx.bars, ${config.name})) | |
197 ${Log::info("e1000::create: pci_request_selected_regions failed")}; | |
198 - if (${config.set_master}) | |
199 - pci_set_master(${pdev}); | |
200 +// XXX if (${config.set_master}) | |
201 +// XXX pci_set_master(${pdev}); | |
202 | |
203 /* 0 here is for BAR_0: */ | |
204 ${rtx_ether_ctx}->hw_ctx.ioaddr = pci_ioremap_bar(${pdev}, 0); | |
205 @@ -630,8 +702,6 @@ | |
206 { | |
207 chunk ::CALL() | |
208 { | |
209 - typedef unsigned long int dma_addr_t; | |
210 - | |
211 /* | |
212 * This part is documented in the Intel Gigabit Ethernet Controller | |
213 * Software Developper manual. (You can find it in the doc/hardware | |
214 @@ -733,7 +803,7 @@ | |
215 hw_ctx->rx_ring.base = dma_alloc_coherent( | |
216 &${ctx}->pci_dev->dev, | |
217 hw_ctx->rx_ring.size, | |
218 - (dma_addr_t *)&hw_ctx->rx_ring.dma_base, | |
219 + &hw_ctx->rx_ring.dma_base, | |
220 GFP_KERNEL); | |
221 if (!hw_ctx->rx_ring.base) | |
222 { | |
223 @@ -758,7 +828,7 @@ | |
224 ${Log::info("cannot allocate a skbuff for the rx ring")}; | |
225 goto err_skbuffs_alloc; | |
226 } | |
227 - hw_ctx->rx_ring.dma_skbuffs[i] = (void *)dma_map_single( | |
228 + hw_ctx->rx_ring.dma_skbuffs[i] = dma_map_single( | |
229 &${ctx}->pci_dev->dev, | |
230 hw_ctx->rx_ring.skbuffs[i]->data, | |
231 ${config.rx_buffer_len}, | |
232 @@ -820,7 +890,7 @@ | |
233 hw_ctx->tx_ring.base = dma_alloc_coherent( | |
234 &${ctx}->pci_dev->dev, | |
235 hw_ctx->tx_ring.size, | |
236 - (dma_addr_t *)&hw_ctx->tx_ring.dma_base, | |
237 + &hw_ctx->tx_ring.dma_base, | |
238 GFP_KERNEL); | |
239 if (!hw_ctx->rx_ring.base) | |
240 { | |
241 @@ -838,6 +908,8 @@ | |
242 /* 3. Setup TDH/TDT to zero: the queue is empty */ | |
243 rtx_e1000_register_write32(hw_ctx, E1000_TDH, 0); | |
244 rtx_e1000_register_write32(hw_ctx, E1000_TDT, 0); | |
245 + hw_ctx->tx_ring.head = 0; | |
246 + hw_ctx->tx_ring.tail = 0; | |
247 | |
248 /* 4. Set TCTL.PSP and enable the transmitter */ | |
249 rtx_e1000_register_set32(hw_ctx, E1000_TCTL, E1000_TCTL_PSP|E1000_TCTL_PSP); | |
250 @@ -930,4 +1002,81 @@ | |
51 } | 251 } |
52 } | 252 } |
53 } | 253 } |
54 + | 254 + |
55 + template sequence e1000::_xmit_tso_cksum_offload(Ethernet::Device ctx, Socket::SKBuff skb) | 255 + template sequence e1000::_xmit_tso_cksum_offload(Ethernet::Device ctx, Socket::SKBuff skb) |
56 + { | 256 + { |
57 + chunk ::CALL() | 257 + chunk ::CALL() |
58 + { | 258 + { |
59 + if (skb_is_gso(${skb}) || ${skb}->ip_summed == CHECKSUM_PARTIAL) | 259 + } |
60 + { | 260 + } |
61 + ${Log::info("xmit: the packet needs to be fragmented and/or checksummed but this not implemented yet!")}; | 261 + |
62 + return NETDEV_TX_OK; | 262 + template sequence e1000::xmit(Ethernet::Device ctx, Socket::KernelSKBuff kernel_skb) |
63 + } | |
64 + } | |
65 + } | |
66 + | |
67 + template sequence e1000::_xmit_map_skbuff(Ethernet::Device ctx, Socket::SKBuff skb) | |
68 + { | 263 + { |
69 + chunk ::CALL() | 264 + chunk ::CALL() |
70 + { | 265 + { |
71 + dma_addr_t buff_addr = dma_map_single( | |
72 + &${ctx}->pci_dev->dev, | |
73 + ${skb}->data, | |
74 + skb_headlen(${skb}), | |
75 + DMA_TO_DEVICE); | |
76 + if (dma_mapping_error(&${ctx}->pci_dev->dev, buff_addr)) | |
77 + { | |
78 + ${Log::info("xmit: can't DMA map a SKBuff")}; | |
79 + goto err_dma_map; | |
80 + } | |
81 + } | |
82 + } | |
83 + | |
84 + template sequence e1000::_xmit_update_tx_ring(Ethernet::Device, Socket::SKBuff skb) | |
85 + { | |
86 + chunk ::CALL() | |
87 + { | |
88 + } | |
89 + } | |
90 + | |
91 + template sequence e1000::xmit(Ethernet::Device ctx, Socket::SKBuff skb) | |
92 + { | |
93 + chunk ::CALL() | |
94 + { | |
95 + typedef unsigned long int dma_addr_t; | |
96 + | |
97 + (void)1; // Issue 10 | |
98 + /* | 266 + /* |
99 + * Put packets on the TX ring, must return NETDEV_TX_OK or | 267 + * Put packets on the TX ring, must return NETDEV_TX_OK or |
100 + * NETDEV_TX_BUSY. | 268 + * NETDEV_TX_BUSY. |
101 + */ | 269 + */ |
102 + { | 270 + |
103 + ${Log::info("xmit: skbuff details:")}; | 271 + /* |
104 + ${skb.dump_infos()}; | 272 + * XXX: This leaves a placeholder if I cast local.tx_ring as |
105 + } | 273 + * e1000::TxRing below. |
274 + */ | |
275 + ${Socket::SKBuff} skb; | |
276 + ${local.skb.init(kernel_skb)}; | |
277 + | |
278 + /* | |
279 + * XXX: can't write ${e1000::TxRing} * (the placeholder isn't | |
280 + * resolved). | |
281 + */ | |
282 + struct rtx_e1000_tx_ring *tx_ring = &${ctx}->hw_ctx.tx_ring; | |
283 + //${cast local.tx_ring as e1000::TxRing}; | |
284 + | |
285 + ${Log::info("xmit: skbuff details:")}; | |
286 + /* | |
287 + * skb is not expand on the bound C variable (should be rtx_skbuff), | |
288 + * which is funny because it works for the sequence template call | |
289 + * right after. | |
290 + */ | |
291 + /* | |
292 + * XXX: doesn't work (I tried to pass self explicitely too): | |
293 + * ${local.skb.dump_infos()}; | |
294 + */ | |
295 + rtx_socket_skbuff_dump_infos(&skb); | |
106 + | 296 + |
107 + /* | 297 + /* |
108 + * The transmission is going to be several steps: | 298 + * The transmission is going to be several steps: |
109 + * 1. TCP Segmentation Offload & Checksum Offloading: pick a | 299 + * 1. TCP Segmentation Offload & Checksum Offloading: pick a |
110 + * descriptor from the tx ring and fill it as a contex | 300 + * descriptor from the tx ring and fill it as a contex |
112 + * according to the MSS; | 302 + * according to the MSS; |
113 + * 2. DMA Map the skbuff data as slices of 4096; | 303 + * 2. DMA Map the skbuff data as slices of 4096; |
114 + * 3. Signal the hardware that data is available via a tx desc. | 304 + * 3. Signal the hardware that data is available via a tx desc. |
115 + */ | 305 + */ |
116 + | 306 + |
307 + /* XXX: same thing wanted to use: ${local.tx_ring.descriptors_remaining()} */ | |
308 + if (!rtx_e1000_tx_ring_descriptors_remaining(tx_ring)) | |
309 + return NETDEV_TX_BUSY; | |
310 + | |
117 + /* 1. Offloading */ | 311 + /* 1. Offloading */ |
118 + { // workaround #10 (and it's useful to workaround #47 too) | 312 + /* XXX: ${local.tx_ring.tso_cksum_offload(skb)}; */ |
119 + ${e1000::_xmit_tso_cksum_offload(ctx, skb)}; | 313 + if (rtx_e1000_tx_ring_tso_cksum_offload(tx_ring, &skb)) |
314 + { | |
315 + ${Log::info("xmit: the packet needs to be fragmented and/or checksummed but this not implemented yet!")}; | |
316 + return NETDEV_TX_OK; | |
120 + } | 317 + } |
121 + | 318 + |
122 + /* 2. Map the data */ | 319 + /* 2. Map the data */ |
123 + { | 320 + ${Device::Device} dev = &${ctx}->pci_dev->dev; |
124 + ${e1000::_xmit_map_skbuff(ctx, skb)}; | 321 + /* XXX: ${local.skb.dma_map(local.dev)}; */ |
125 + } | 322 + rtx_socket_dma_map(&skb, dev); |
126 + | 323 + |
127 + /* 3. Update the TX Ring */ | 324 + /* 3. Update the TX Ring */ |
128 + { | 325 + /* XXX: ${local.tx_ring.put(skb)}; */ |
129 + ${e1000::_xmit_update_tx_ring(ctx, skb)}; | 326 + rtx_e1000_tx_ring_put(tx_ring, &skb); |
130 + } | 327 + |
131 + | |
132 + err_dma_map: | |
133 + return NETDEV_TX_OK; | 328 + return NETDEV_TX_OK; |
134 + } | 329 + } |
135 + } | 330 + } |
136 } | 331 } |
137 diff --git a/rathaxes/samples/e1000/e1000.rti b/rathaxes/samples/e1000/e1000.rti | 332 diff --git a/rathaxes/samples/e1000/e1000.rti b/rathaxes/samples/e1000/e1000.rti |
138 --- a/rathaxes/samples/e1000/e1000.rti | 333 --- a/rathaxes/samples/e1000/e1000.rti |
139 +++ b/rathaxes/samples/e1000/e1000.rti | 334 +++ b/rathaxes/samples/e1000/e1000.rti |
140 @@ -51,6 +51,12 @@ | 335 @@ -31,8 +31,14 @@ |
336 provided type TxRing | |
337 { | |
338 chunk LKM::includes(); | |
339 + chunk LKM::prototypes(); | |
340 + chunk LKM::code(); | |
341 method decl(); | |
342 method init(); | |
343 + | |
344 + method descriptors_remaining(); | |
345 + method tso_cksum_offload(Socket::SKBuff); | |
346 + method put(Socket::SKBuff); | |
347 } | |
348 | |
349 /* | |
350 @@ -51,6 +57,12 @@ | |
141 method decl(); | 351 method decl(); |
142 } | 352 } |
143 | 353 |
144 + provided type TxFlags | 354 + provided type TxFlags |
145 + { | 355 + { |
148 + } | 358 + } |
149 + | 359 + |
150 provided sequence create_device() | 360 provided sequence create_device() |
151 { | 361 { |
152 provided chunk Ethernet::create_device(PCI::Device, Ethernet::Device); | 362 provided chunk Ethernet::create_device(PCI::Device, Ethernet::Device); |
153 @@ -109,6 +115,26 @@ | 363 @@ -109,6 +121,16 @@ |
154 provided chunk ::CALL(); | 364 provided chunk ::CALL(); |
155 } | 365 } |
156 | 366 |
157 + provided sequence _xmit_tso_cksum_offload(Ethernet::Device, Socket::SKBuff) | 367 + provided sequence _xmit_tso_cksum_offload(Ethernet::Device, Socket::SKBuff) |
158 + { | 368 + { |
159 + provided chunk ::CALL(); | 369 + provided chunk ::CALL(); |
160 + } | 370 + } |
161 + | 371 + |
162 + provided sequence _xmit_map_skbuff(Ethernet::Device, Socket::SKBuff) | 372 + provided sequence xmit(Ethernet::Device, Socket::KernelSKBuff) |
163 + { | |
164 + provided chunk ::CALL(); | |
165 + } | |
166 + | |
167 + provided sequence _xmit_update_tx_ring(Ethernet::Device, Socket::SKBuff) | |
168 + { | |
169 + provided chunk ::CALL(); | |
170 + } | |
171 + | |
172 + provided sequence xmit(Ethernet::Device, Socket::SKBuff) | |
173 + { | 373 + { |
174 + provided chunk ::CALL(); | 374 + provided chunk ::CALL(); |
175 + } | 375 + } |
176 + | 376 + |
177 provided sequence register_read32(e1000::Context, e1000::Register) | 377 provided sequence register_read32(e1000::Context, e1000::Register) |
178 { | 378 { |
179 provided chunk LKM::prototypes(); | 379 provided chunk LKM::prototypes(); |
180 diff --git a/rathaxes/samples/e1000/ethernet.blt b/rathaxes/samples/e1000/ethernet.blt | 380 diff --git a/rathaxes/samples/e1000/ethernet.blt b/rathaxes/samples/e1000/ethernet.blt |
181 --- a/rathaxes/samples/e1000/ethernet.blt | 381 --- a/rathaxes/samples/e1000/ethernet.blt |
182 +++ b/rathaxes/samples/e1000/ethernet.blt | 382 +++ b/rathaxes/samples/e1000/ethernet.blt |
183 @@ -1,6 +1,51 @@ | 383 @@ -1,6 +1,56 @@ |
184 with Ethernet, PCI, LKM, Log | 384 with Ethernet, PCI, LKM, Log |
185 { | 385 { |
186 - template type Ethernet::Net() | 386 - template type Ethernet::Net() |
187 + template type Ethernet::ProtocolId() | 387 + template type Ethernet::ProtocolId() |
188 + { | 388 + { |
217 + | 417 + |
218 + return "Unknown"; | 418 + return "Unknown"; |
219 + } | 419 + } |
220 + } | 420 + } |
221 + | 421 + |
422 + chunk decl() | |
423 + { | |
424 + typedef unsigned short rtx_ether_protocol_id; | |
425 + } | |
426 + | |
222 + chunk to_str() | 427 + chunk to_str() |
223 + { | 428 + { |
224 + rtx_ethernet_protocol_id_to_str(${self}); | 429 + rtx_ethernet_protocol_id_to_str(${self}); |
225 + } | 430 + } |
226 + | 431 + |
231 + | 436 + |
232 + template type Ethernet::AbstractDevice() | 437 + template type Ethernet::AbstractDevice() |
233 { | 438 { |
234 chunk LKM::includes() | 439 chunk LKM::includes() |
235 { | 440 { |
236 @@ -17,11 +62,6 @@ | 441 @@ -17,11 +67,6 @@ |
237 } | 442 } |
238 } | 443 } |
239 | 444 |
240 - /* | 445 - /* |
241 - * Unlike PCI::Device, Ethernet::Device doesn't match the struct net_device | 446 - * Unlike PCI::Device, Ethernet::Device doesn't match the struct net_device |
243 - * field of the struct net_device. | 448 - * field of the struct net_device. |
244 - */ | 449 - */ |
245 template type Ethernet::Device() | 450 template type Ethernet::Device() |
246 { | 451 { |
247 chunk LKM::includes() | 452 chunk LKM::includes() |
248 @@ -52,7 +92,7 @@ | 453 @@ -47,15 +92,15 @@ |
454 struct pci_dev *pci_dev; | |
455 struct net_device *net_dev; | |
456 | |
457 - /* while waiting on issue #8 */ | |
458 - //${e1000::Context} hw_ctx; | |
459 - // In the long-term, this may disappear for a new concept allowing | |
460 - // to embbed a descriptor defined and manipulated by the front-end | |
461 + /* | |
462 + * In the long-term, this may disappear for a new concept allowing | |
463 + * to embbed a descriptor defined and manipulated by the front-end | |
464 + */ | |
465 ${pointcut Ethernet::SubContext()}; | |
249 } *rtx_ethernet_dev_p; | 466 } *rtx_ethernet_dev_p; |
250 } | 467 } |
251 | 468 |
252 - chunk ::init(Ethernet::Net net_dev, PCI::Device pci_dev) | 469 - chunk ::init(Ethernet::Net net_dev, PCI::Device pci_dev) |
253 + chunk ::init(Ethernet::AbstractDevice net_dev, PCI::Device pci_dev) | 470 + chunk ::init(Ethernet::AbstractDevice net_dev, PCI::Device pci_dev) |
254 { | 471 { |
255 ${self} = netdev_priv(${net_dev}); | 472 ${self} = netdev_priv(${net_dev}); |
256 /* | 473 /* |
257 @@ -100,11 +140,11 @@ | 474 @@ -82,9 +127,8 @@ |
258 { | 475 { |
259 static int rtx_ethernet_xmit(struct sk_buff* skb, struct net_device *dev) | 476 static int rtx_ethernet_open(struct net_device *dev) |
477 { | |
478 - struct rtx_ethernet_dev* rtx_ether_dev = netdev_priv(dev); | |
479 + ${Ethernet::Device} rtx_ether_dev = netdev_priv(dev); | |
480 | |
481 - ${cast local.rtx_ether_dev as Ethernet::Device}; | |
482 ${pointcut ::IMPLEMENTATION(local.rtx_ether_dev)}; | |
483 | |
484 return 0; | |
485 @@ -92,7 +136,7 @@ | |
486 } | |
487 } | |
488 | |
489 - template sequence Ethernet::send(Ethernet::Device dev, Socket::SKBuff skb) | |
490 + template sequence Ethernet::send(Ethernet::Device dev, Socket::KernelSKBuff skb) | |
491 { | |
492 chunk LKM::prototypes() | |
493 { | |
494 @@ -101,13 +145,11 @@ | |
495 | |
496 chunk LKM::code() | |
497 { | |
498 - static int rtx_ethernet_xmit(struct sk_buff* skb, struct net_device *dev) | |
499 + static int rtx_ethernet_xmit(struct sk_buff* kernel_skb, struct net_device *net_dev) | |
260 { | 500 { |
261 - ${cast local.dev as Ethernet::Device}; | 501 - ${cast local.dev as Ethernet::Device}; |
262 + struct rtx_ethernet_dev* rtx_ethernet_dev = netdev_priv(dev); | 502 - ${cast local.skb as Socket::SKBuff}; |
263 + | |
264 + ${cast local.rtx_ethernet_dev as Ethernet::Device}; | |
265 ${cast local.skb as Socket::SKBuff}; | |
266 - ${pointcut ::IMPLEMENTATION(local.dev, local.skb)}; | 503 - ${pointcut ::IMPLEMENTATION(local.dev, local.skb)}; |
267 - | 504 - |
268 - return 0; | 505 - return 0; |
269 + ${pointcut ::IMPLEMENTATION(local.rtx_ethernet_dev, local.skb)}; | 506 + ${Ethernet::Device} rtx_ethernet_dev = netdev_priv(net_dev); |
507 + ${cast local.kernel_skb as Socket::KernelSKBuff}; | |
508 + ${pointcut ::IMPLEMENTATION(local.rtx_ethernet_dev, local.kernel_skb)}; | |
270 } | 509 } |
271 } | 510 } |
272 } | 511 } |
512 @@ -123,9 +165,8 @@ | |
513 { | |
514 static int rtx_ethernet_close(struct net_device *dev) | |
515 { | |
516 - struct rtx_ethernet_dev* rtx_ether_dev = netdev_priv(dev); | |
517 + ${Ethernet::Device} rtx_ether_dev = netdev_priv(dev); | |
518 | |
519 - ${cast local.rtx_ether_dev as Ethernet::Device}; | |
520 ${pointcut ::IMPLEMENTATION(local.rtx_ether_dev)}; | |
521 | |
522 return 0; | |
523 @@ -148,11 +189,8 @@ | |
524 { | |
525 static enum irqreturn rtx_ethernet_interrupt_handler(int irq, void *dev_id) | |
526 { | |
527 - struct rtx_ethernet_dev* rtx_ether_dev; | |
528 - struct rtx_e1000_ctx* ctx; | |
529 + ${Ethernet::Device} rtx_ether_dev = dev_id; | |
530 | |
531 - rtx_ether_dev = dev_id; | |
532 - ${cast local.rtx_ether_dev as Ethernet::Device}; | |
533 ${pointcut ::IMPLEMENTATION(local.rtx_ether_dev)}; | |
534 | |
535 return IRQ_NONE; | |
273 diff --git a/rathaxes/samples/e1000/ethernet.rti b/rathaxes/samples/e1000/ethernet.rti | 536 diff --git a/rathaxes/samples/e1000/ethernet.rti b/rathaxes/samples/e1000/ethernet.rti |
274 --- a/rathaxes/samples/e1000/ethernet.rti | 537 --- a/rathaxes/samples/e1000/ethernet.rti |
275 +++ b/rathaxes/samples/e1000/ethernet.rti | 538 +++ b/rathaxes/samples/e1000/ethernet.rti |
276 @@ -1,16 +1,33 @@ | 539 @@ -1,16 +1,30 @@ |
277 interface Ethernet : Socket, PCI, LKM | 540 interface Ethernet : Socket, PCI, LKM |
278 { | 541 { |
279 - provided type Net | 542 - provided type Net |
280 + provided type ProtocolId | 543 + provided type ProtocolId |
281 + { | 544 + { |
282 + chunk LKM::prototypes(); | 545 + chunk LKM::prototypes(); |
283 + chunk LKM::data(); | 546 + chunk LKM::data(); |
284 + chunk LKM::code(); | 547 + chunk LKM::code(); |
285 + method ::to_str(); | 548 + method decl(); |
286 + } | 549 + method to_str(); |
287 + | 550 + } |
288 + /* | 551 + |
289 + * This is the abstract type used by the Kernel to represent an ethernet | |
290 + * device. | |
291 + */ | |
292 + provided type AbstractDevice | 552 + provided type AbstractDevice |
293 { | 553 { |
294 chunk LKM::includes(); | 554 chunk LKM::includes(); |
295 method decl(); | 555 - method decl(); |
556 + method decl(); | |
296 } | 557 } |
297 | 558 |
298 + /* | 559 + /* |
299 + * Unlike PCI::Device, Ethernet::Device doesn't match the struct net_device | 560 + * Unlike PCI::Device, Ethernet::Device doesn't match the struct net_device |
300 + * from Linux. Ethernet::Device is the type that we use in the private | 561 + * from Linux. Ethernet::Device is the type that we use in the private |
304 { | 565 { |
305 chunk LKM::includes(); | 566 chunk LKM::includes(); |
306 method decl(); | 567 method decl(); |
307 - method init(Ethernet::Net, PCI::Device); | 568 - method init(Ethernet::Net, PCI::Device); |
308 + method init(Ethernet::AbstractDevice, PCI::Device); | 569 + method init(Ethernet::AbstractDevice, PCI::Device); |
309 } | 570 pointcut Ethernet::SubContext(); |
310 | 571 } |
311 required variable ::string ifname; | 572 |
573 @@ -22,7 +36,7 @@ | |
574 provided chunk LKM::code(); | |
575 } | |
576 | |
577 - required sequence send(Ethernet::Device dev, Socket::SKBuff skb) | |
578 + required sequence send(Ethernet::Device, Socket::KernelSKBuff) | |
579 { | |
580 provided chunk LKM::prototypes(); | |
581 provided chunk LKM::code(); | |
312 diff --git a/rathaxes/samples/e1000/lkm.rtx b/rathaxes/samples/e1000/lkm.rtx | 582 diff --git a/rathaxes/samples/e1000/lkm.rtx b/rathaxes/samples/e1000/lkm.rtx |
313 --- a/rathaxes/samples/e1000/lkm.rtx | 583 --- a/rathaxes/samples/e1000/lkm.rtx |
314 +++ b/rathaxes/samples/e1000/lkm.rtx | 584 +++ b/rathaxes/samples/e1000/lkm.rtx |
315 @@ -46,6 +46,7 @@ | 585 @@ -1,4 +1,4 @@ |
316 Ethernet::send(Ethernet::Device dev, Socket::SKBuff skb) | 586 -device LKM use LKM, PCI, Ethernet, Log |
587 +device LKM use LKM, PCI, Ethernet, Log, Socket | |
588 { | |
589 Ethernet::open(Ethernet::Device dev) | |
590 { | |
591 @@ -43,9 +43,10 @@ | |
592 e1000::handle_interrupt(dev); | |
593 } | |
594 | |
595 - Ethernet::send(Ethernet::Device dev, Socket::SKBuff skb) | |
596 + Ethernet::send(Ethernet::Device dev, Socket::KernelSKBuff skb) | |
317 { | 597 { |
318 Log::info("we have one packet to transmit!"); | 598 Log::info("we have one packet to transmit!"); |
319 + e1000::xmit(dev, skb); | 599 + e1000::xmit(dev, skb); |
320 } | 600 } |
321 | 601 |
332 + e1000::tx_max_data_per_desc = 4096; | 612 + e1000::tx_max_data_per_desc = 4096; |
333 } | 613 } |
334 diff --git a/rathaxes/samples/e1000/socket.blt b/rathaxes/samples/e1000/socket.blt | 614 diff --git a/rathaxes/samples/e1000/socket.blt b/rathaxes/samples/e1000/socket.blt |
335 --- a/rathaxes/samples/e1000/socket.blt | 615 --- a/rathaxes/samples/e1000/socket.blt |
336 +++ b/rathaxes/samples/e1000/socket.blt | 616 +++ b/rathaxes/samples/e1000/socket.blt |
337 @@ -1,4 +1,4 @@ | 617 @@ -1,20 +1,104 @@ |
338 -with Socket, LKM | 618 -with Socket, LKM |
339 +with Socket, LKM, Ethernet | 619 +with Socket, LKM, Device, Ethernet |
340 { | 620 { |
621 + template type Socket::KernelSKBuff() | |
622 + { | |
623 + chunk LKM::includes() | |
624 + { | |
625 + #include <linux/skbuff.h> | |
626 + | |
627 + static const ${Socket::KernelSKBuff} force_rtx_socket_kernel_skbuff_decl; | |
628 + } | |
629 + | |
630 + chunk ::decl() | |
631 + { | |
632 + typedef struct sk_buff *rtx_socket_kernel_skbuff_p; | |
633 + } | |
634 + | |
635 + map | |
636 + { | |
637 + } | |
638 + } | |
639 + | |
341 template type Socket::SKBuff() | 640 template type Socket::SKBuff() |
342 { | 641 { |
343 @@ -10,13 +10,41 @@ | 642 chunk LKM::includes() |
643 { | |
644 - #include <linux/skbuff.h> | |
645 - static const ${Socket::SKBuff} force_rtx_lnux_skbuf_decl; | |
646 + static const ${Socket::SKBuff} force_rtx_socket_skbuff_decl; | |
647 } | |
344 | 648 |
345 chunk ::decl() | 649 chunk ::decl() |
346 { | 650 { |
347 - struct sk_buff; | 651 - struct sk_buff; |
348 + typedef struct sk_buff *rtx_socket_skbuff_p; | 652 + struct rtx_socket_skbuff |
349 } | 653 + { |
350 | 654 + struct sk_buff *skbuff; |
351 chunk ::init() | 655 + dma_addr_t dma_handle; |
352 { | |
353 } | |
354 | |
355 + chunk ::dump_infos() | |
356 + { | |
357 + /* | |
358 + * We should use a Rathaxes log abstraction instead of pr_info here, | |
359 + * but Rathaxes doesn't support functions with a variable number of | |
360 + * arguments yet. | |
361 + */ | |
362 + unsigned short ethernet_proto = be16_to_cpu(${self}->protocol); | |
363 + ${cast local.ethernet_proto as Ethernet::ProtocolId}; | |
364 + | |
365 + static const char * const ip_summed_values[] = { | |
366 + "none", "unnecessary", "complete", "partial" | |
367 + }; | 656 + }; |
368 + | 657 } |
369 + pr_info( | 658 |
370 + "\t protocol = %#-5x (%s)\n" | 659 - chunk ::init() |
371 + "\t len = %-5u data_len = %-5u head_len = %-5u\n" | 660 + chunk LKM::prototypes() |
372 + "\t nr_frags = %u\n" | 661 { |
373 + "\t gso_size = %-5u gso_segs = %-5u gso_type = %-5u\n" | 662 + static void rtx_socket_skbuff_dump_infos(struct rtx_socket_skbuff *); |
374 + "\tip_summed = %d (%s)", | 663 + static int rtx_socket_dma_map(struct rtx_socket_skbuff *, struct device *); |
375 + ethernet_proto, "", // XXX: ${local.ethernet_proto.to_str()}, | 664 + } |
376 + ${self}->len, ${self}->data_len, skb_headlen(${self}), | 665 + |
377 + skb_shinfo(${self})->nr_frags, | 666 + chunk LKM::code() |
378 + skb_shinfo(${self})->gso_size, skb_shinfo(${self})->gso_segs, skb_shinfo(${self})->gso_type, | 667 + { |
379 + ${self}->ip_summed, ip_summed_values[${self}->ip_summed] | 668 + static void rtx_socket_skbuff_dump_infos(struct rtx_socket_skbuff *self) |
380 + ); | 669 + { |
381 + } | 670 + /* |
382 + | 671 + * We should use a Rathaxes log abstraction instead of pr_info here, |
672 + * but Rathaxes doesn't support functions with a variable number of | |
673 + * arguments yet. | |
674 + */ | |
675 + ${Ethernet::ProtocolId} ethernet_proto = be16_to_cpu(self->skbuff->protocol); | |
676 + static const char * const ip_summed_values[] = { | |
677 + "none", "unnecessary", "complete", "partial" | |
678 + }; | |
679 + struct skb_shared_info *shinfo = skb_shinfo(self->skbuff); | |
680 + | |
681 + pr_info( | |
682 + "\t protocol = %#-5x (%s)\n" | |
683 + "\t len = %-5u data_len = %-5u head_len = %-5u\n" | |
684 + "\t nr_frags = %u\n" | |
685 + "\t gso_size = %-5u gso_segs = %-5u gso_type = %-5u\n" | |
686 + "\tip_summed = %d (%s)", | |
687 + ethernet_proto, rtx_ethernet_protocol_id_to_str(ethernet_proto) /* XXX: ${local.ethernet_proto.to_str()} */, | |
688 + self->skbuff->len, self->skbuff->data_len, skb_headlen(self->skbuff), | |
689 + shinfo->nr_frags, shinfo->gso_size, shinfo->gso_segs, shinfo->gso_type, | |
690 + self->skbuff->ip_summed, ip_summed_values[self->skbuff->ip_summed] | |
691 + ); | |
692 + } | |
693 + | |
694 + static int rtx_socket_dma_map(struct rtx_socket_skbuff *self, struct device *dev) | |
695 + { | |
696 + self->dma_handle = dma_map_single( | |
697 + dev, | |
698 + self->skbuff->data, | |
699 + skb_headlen(self->skbuff), | |
700 + DMA_TO_DEVICE); | |
701 + return dma_mapping_error(dev, self->dma_handle); | |
702 + } | |
703 + } | |
704 + | |
705 + /* | |
706 + * XXX: the rathaxes argument kernel_skb is not actually bound to the | |
707 + * correct C variable from Ethernet::send() (so I named it as the C | |
708 + * variable I needed) | |
709 + */ | |
710 + chunk ::init(Socket::KernelSKBuff kernel_skb) | |
711 + { | |
712 + ${self}.skbuff = kernel_skb; | |
713 + ${self}.dma_handle = 0; | |
714 + } | |
715 + | |
716 + chunk dump_infos() | |
717 + { | |
718 + rtx_socket_skbuff_dump_infos(${self}); | |
719 + } | |
720 + | |
721 + chunk dma_map(Device::Device dev) | |
722 + { | |
723 + rtx_socket_dma_map(${self}, ${dev}); | |
724 } | |
725 | |
383 map | 726 map |
384 { | |
385 // some work may have to be done here in order | |
386 diff --git a/rathaxes/samples/e1000/socket.rti b/rathaxes/samples/e1000/socket.rti | 727 diff --git a/rathaxes/samples/e1000/socket.rti b/rathaxes/samples/e1000/socket.rti |
387 --- a/rathaxes/samples/e1000/socket.rti | 728 --- a/rathaxes/samples/e1000/socket.rti |
388 +++ b/rathaxes/samples/e1000/socket.rti | 729 +++ b/rathaxes/samples/e1000/socket.rti |
389 @@ -1,8 +1,10 @@ | 730 @@ -1,8 +1,19 @@ |
390 interface Socket : LKM | 731 -interface Socket : LKM |
732 +interface Socket : LKM, Device | |
391 { | 733 { |
392 - provided type Socket::SKBuff { | 734 - provided type Socket::SKBuff { |
393 + provided type Socket::SKBuff | 735 - chunk LKM::includes(); |
394 + { | |
395 chunk LKM::includes(); | |
396 - method decl(); | 736 - method decl(); |
397 - method init(); | 737 - method init(); |
398 + chunk ::decl(); | 738 + provided type KernelSKBuff |
399 + method ::init(); | 739 + { |
400 + method ::dump_infos(); | 740 + chunk LKM::includes(); |
741 + method decl(); | |
742 + } | |
743 + | |
744 + provided type SKBuff | |
745 + { | |
746 + chunk LKM::includes(); | |
747 + chunk LKM::prototypes(); | |
748 + chunk LKM::code(); | |
749 + method decl(); | |
750 + method init(Socket::KernelSKBuff); | |
751 + method dump_infos(); | |
752 + method dma_map(Device::Device); | |
401 } | 753 } |
402 } | 754 } |