1 From 9caa6a8cab0d7f46475990aaeb7dcc7721547ef0 Mon Sep 17 00:00:00 2001
2 From: Jan Kiszka <jan.kiszka@siemens.com>
3 Date: Mon, 5 Dec 2016 15:43:53 +0100
4 Subject: [PATCH 32/32] ivshmem-net: Adjust to reworked version of ivshmem in
7 This contains the changes required to work with the new revision of
8 ivshmem in Jailhouse, namely:
10 - changed PCI vendor and device ID
11 - vendor capability to communicate region location
12 - new MMIO register layout
13 - common interrupt control register
14 - state table support, removal of rstate register
15 - unidirectional shared memory regions
16 - vector value has to be written to doorbell register
17 - support for multiple vectors, used to split config from tx-rx
19 Note: Specification work for the interface is ongoing, so details may
22 Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
24 drivers/net/ivshmem-net.c | 335 ++++++++++++++++++++++++++++++----------------
25 1 file changed, 223 insertions(+), 112 deletions(-)
27 diff --git a/drivers/net/ivshmem-net.c b/drivers/net/ivshmem-net.c
28 index 9946cef63c1f..18d5a15dbec2 100644
29 --- a/drivers/net/ivshmem-net.c
30 +++ b/drivers/net/ivshmem-net.c
33 * Copyright 2016 Mans Rullgard <mans@mansr.com>
34 + * Copyright (c) Siemens AG, 2016-2020
36 * This program is free software; you can redistribute it and/or modify
37 * it under the terms of the GNU General Public License as published by
39 * along with this program; if not, see <http://www.gnu.org/licenses/>.
42 +#include <linux/ivshmem.h>
43 #include <linux/kernel.h>
44 #include <linux/module.h>
45 #include <linux/pci.h>
48 #define DRV_NAME "ivshmem-net"
50 -#define JAILHOUSE_CFG_SHMEM_PTR 0x40
51 -#define JAILHOUSE_CFG_SHMEM_SZ 0x48
52 +#define IVSHM_NET_STATE_RESET 0
53 +#define IVSHM_NET_STATE_INIT 1
54 +#define IVSHM_NET_STATE_READY 2
55 +#define IVSHM_NET_STATE_RUN 3
57 -#define IVSHMEM_INTX_ENABLE 0x1
58 +#define IVSHM_NET_FLAG_RUN 0
60 -#define IVSHM_NET_STATE_RESET 0
61 -#define IVSHM_NET_STATE_INIT 1
62 -#define IVSHM_NET_STATE_READY 2
63 -#define IVSHM_NET_STATE_RUN 3
65 -#define IVSHM_NET_FLAG_RUN 0
67 -#define IVSHM_NET_MTU_MIN 256
68 -#define IVSHM_NET_MTU_MAX 65535
69 -#define IVSHM_NET_MTU_DEF 16384
70 +#define IVSHM_NET_MTU_MIN 256
71 +#define IVSHM_NET_MTU_MAX 65535
72 +#define IVSHM_NET_MTU_DEF 16384
74 #define IVSHM_NET_FRAME_SIZE(s) ALIGN(18 + (s), SMP_CACHE_BYTES)
76 #define IVSHM_NET_VQ_ALIGN 64
78 -struct ivshmem_regs {
86 +#define IVSHM_NET_SECTION_TX 0
87 +#define IVSHM_NET_SECTION_RX 1
89 +#define IVSHM_NET_MSIX_STATE 0
90 +#define IVSHM_NET_MSIX_TX_RX 1
92 +#define IVSHM_NET_NUM_VECTORS 2
94 struct ivshm_net_queue {
96 @@ -73,7 +69,7 @@ struct ivshm_net_queue {
99 struct ivshm_net_stats {
101 + u32 tx_rx_interrupts;
105 @@ -97,8 +93,9 @@ struct ivshm_net {
107 struct napi_struct napi;
112 + u32 last_peer_state;
117 @@ -107,17 +104,19 @@ struct ivshm_net {
119 struct ivshm_net_stats stats;
121 - struct ivshmem_regs __iomem *ivshm_regs;
123 - phys_addr_t shmaddr;
124 + struct ivshm_regs __iomem *ivshm_regs;
126 resource_size_t shmlen;
131 struct pci_dev *pdev;
134 static void *ivshm_net_desc_data(struct ivshm_net *in,
135 struct ivshm_net_queue *q,
136 + unsigned int region,
137 struct vring_desc *desc,
140 @@ -132,7 +131,7 @@ static void *ivshm_net_desc_data(struct ivshm_net *in,
141 if (offs >= in->shmlen)
144 - data = in->shm + offs;
145 + data = in->shm[region] + offs;
147 if (data < q->data || data >= q->end)
149 @@ -160,18 +159,17 @@ static void ivshm_net_init_queue(struct ivshm_net *in,
150 static void ivshm_net_init_queues(struct net_device *ndev)
152 struct ivshm_net *in = netdev_priv(ndev);
153 - int ivpos = readl(&in->ivshm_regs->ivpos);
158 - tx = in->shm + ivpos * in->shmlen / 2;
159 - rx = in->shm + !ivpos * in->shmlen / 2;
160 + tx = in->shm[IVSHM_NET_SECTION_TX];
161 + rx = in->shm[IVSHM_NET_SECTION_RX];
163 - memset(tx, 0, in->shmlen / 2);
164 + memset(tx, 0, in->shmlen);
166 - ivshm_net_init_queue(in, &in->rx, rx, in->qlen);
167 ivshm_net_init_queue(in, &in->tx, tx, in->qlen);
168 + ivshm_net_init_queue(in, &in->rx, rx, in->qlen);
170 swap(in->rx.vr.used, in->tx.vr.used);
172 @@ -191,14 +189,14 @@ static int ivshm_net_calc_qsize(struct net_device *ndev)
173 for (qlen = 4096; qlen > 32; qlen >>= 1) {
174 vrsize = vring_size(qlen, IVSHM_NET_VQ_ALIGN);
175 vrsize = ALIGN(vrsize, IVSHM_NET_VQ_ALIGN);
176 - if (vrsize < in->shmlen / 16)
177 + if (vrsize < in->shmlen / 8)
181 - if (vrsize > in->shmlen / 2)
182 + if (vrsize > in->shmlen)
185 - qsize = in->shmlen / 2 - vrsize;
186 + qsize = in->shmlen - vrsize;
188 if (qsize < 4 * IVSHM_NET_MTU_MIN)
190 @@ -221,7 +219,8 @@ static void ivshm_net_notify_tx(struct ivshm_net *in, unsigned int num)
191 new = in->tx.last_avail_idx;
193 if (vring_need_event(evt, new, old)) {
194 - writel(in->peer_id << 16, &in->ivshm_regs->doorbell);
195 + writel(in->tx_rx_vector | (in->peer_id << 16),
196 + &in->ivshm_regs->doorbell);
197 in->stats.tx_notify++;
200 @@ -243,7 +242,8 @@ static void ivshm_net_notify_rx(struct ivshm_net *in, unsigned int num)
201 new = in->rx.last_used_idx;
203 if (vring_need_event(evt, new, old)) {
204 - writel(in->peer_id << 16, &in->ivshm_regs->doorbell);
205 + writel(in->tx_rx_vector | (in->peer_id << 16),
206 + &in->ivshm_regs->doorbell);
207 in->stats.rx_notify++;
210 @@ -320,7 +320,7 @@ static int ivshm_net_tx_frame(struct net_device *ndev, struct sk_buff *skb,
211 buf = tx->data + head;
212 skb_copy_and_csum_dev(skb, buf);
214 - desc->addr = buf - in->shm;
215 + desc->addr = buf - in->shm[IVSHM_NET_SECTION_TX];
216 desc->len = skb->len;
219 @@ -374,7 +374,8 @@ static void ivshm_net_tx_clean(struct net_device *ndev)
221 desc = &vr->desc[used->id];
223 - data = ivshm_net_desc_data(in, &in->tx, desc, &len);
224 + data = ivshm_net_desc_data(in, &in->tx, IVSHM_NET_SECTION_TX,
227 netdev_err(ndev, "bad tx descriptor, data == NULL\n");
229 @@ -466,7 +467,8 @@ static int ivshm_net_poll(struct napi_struct *napi, int budget)
233 - data = ivshm_net_desc_data(in, &in->rx, desc, &len);
234 + data = ivshm_net_desc_data(in, &in->rx, IVSHM_NET_SECTION_RX,
237 netdev_err(ndev, "bad rx descriptor\n");
239 @@ -535,15 +537,15 @@ static netdev_tx_t ivshm_net_xmit(struct sk_buff *skb, struct net_device *ndev)
240 static void ivshm_net_set_state(struct ivshm_net *in, u32 state)
243 - WRITE_ONCE(in->lstate, state);
244 - writel(state, &in->ivshm_regs->lstate);
245 + WRITE_ONCE(in->state, state);
246 + writel(state, &in->ivshm_regs->state);
249 static void ivshm_net_run(struct net_device *ndev)
251 struct ivshm_net *in = netdev_priv(ndev);
253 - if (in->lstate < IVSHM_NET_STATE_READY)
254 + if (in->state < IVSHM_NET_STATE_READY)
257 if (!netif_running(ndev))
258 @@ -575,15 +577,15 @@ static void ivshm_net_state_change(struct work_struct *work)
260 struct ivshm_net *in = container_of(work, struct ivshm_net, state_work);
261 struct net_device *ndev = in->napi.dev;
262 - u32 rstate = readl(&in->ivshm_regs->rstate);
263 + u32 peer_state = READ_ONCE(in->state_table[in->peer_id]);
265 - switch (in->lstate) {
266 + switch (in->state) {
267 case IVSHM_NET_STATE_RESET:
269 * Wait for the remote to leave READY/RUN before transitioning
272 - if (rstate < IVSHM_NET_STATE_READY)
273 + if (peer_state < IVSHM_NET_STATE_READY)
274 ivshm_net_set_state(in, IVSHM_NET_STATE_INIT);
277 @@ -592,7 +594,7 @@ static void ivshm_net_state_change(struct work_struct *work)
278 * Wait for the remote to leave RESET before performing the
279 * initialization and moving to READY.
281 - if (rstate > IVSHM_NET_STATE_RESET) {
282 + if (peer_state > IVSHM_NET_STATE_RESET) {
283 ivshm_net_init_queues(ndev);
284 ivshm_net_set_state(in, IVSHM_NET_STATE_READY);
286 @@ -607,7 +609,7 @@ static void ivshm_net_state_change(struct work_struct *work)
287 * Link is up and we are running once the remote is in READY or
290 - if (rstate >= IVSHM_NET_STATE_READY) {
291 + if (peer_state >= IVSHM_NET_STATE_READY) {
292 netif_carrier_on(ndev);
295 @@ -617,7 +619,7 @@ static void ivshm_net_state_change(struct work_struct *work)
297 * If the remote goes to RESET, we need to follow immediately.
299 - if (rstate == IVSHM_NET_STATE_RESET) {
300 + if (peer_state == IVSHM_NET_STATE_RESET) {
301 netif_carrier_off(ndev);
302 ivshm_net_do_stop(ndev);
304 @@ -625,31 +627,44 @@ static void ivshm_net_state_change(struct work_struct *work)
308 - WRITE_ONCE(in->rstate, rstate);
309 + WRITE_ONCE(in->last_peer_state, peer_state);
312 -static void ivshm_net_check_state(struct net_device *ndev)
313 +static void ivshm_net_check_state(struct ivshm_net *in)
315 - struct ivshm_net *in = netdev_priv(ndev);
316 - u32 rstate = readl(&in->ivshm_regs->rstate);
318 - if (rstate != in->rstate || !test_bit(IVSHM_NET_FLAG_RUN, &in->flags))
319 + if (in->state_table[in->peer_id] != in->last_peer_state ||
320 + !test_bit(IVSHM_NET_FLAG_RUN, &in->flags))
321 queue_work(in->state_wq, &in->state_work);
324 -static irqreturn_t ivshm_net_int(int irq, void *data)
325 +static irqreturn_t ivshm_net_int_state(int irq, void *data)
327 - struct net_device *ndev = data;
328 - struct ivshm_net *in = netdev_priv(ndev);
329 + struct ivshm_net *in = data;
331 + ivshm_net_check_state(in);
333 + return IRQ_HANDLED;
336 - in->stats.interrupts++;
337 +static irqreturn_t ivshm_net_int_tx_rx(int irq, void *data)
339 + struct ivshm_net *in = data;
341 + in->stats.tx_rx_interrupts++;
343 - ivshm_net_check_state(ndev);
344 napi_schedule_irqoff(&in->napi);
349 +static irqreturn_t ivshm_net_intx(int irq, void *data)
351 + ivshm_net_int_state(irq, data);
352 + ivshm_net_int_tx_rx(irq, data);
354 + return IRQ_HANDLED;
357 static int ivshm_net_open(struct net_device *ndev)
359 netdev_reset_queue(ndev);
360 @@ -717,7 +732,7 @@ static const struct net_device_ops ivshm_net_ops = {
363 static const char ivshm_net_stats[][ETH_GSTRING_LEN] = {
365 + "tx_rx_interrupts",
369 @@ -760,7 +775,7 @@ static void ivshm_net_get_ethtool_stats(struct net_device *ndev,
373 - st[n++] = in->stats.interrupts;
374 + st[n++] = in->stats.tx_rx_interrupts;
375 st[n++] = in->stats.tx_packets;
376 st[n++] = in->stats.tx_notify;
377 st[n++] = in->stats.tx_pause;
378 @@ -789,8 +804,8 @@ static void ivshm_net_get_regs(struct net_device *ndev,
382 - *reg32++ = in->lstate;
383 - *reg32++ = in->rstate;
384 + *reg32++ = in->state;
385 + *reg32++ = in->last_peer_state;
388 reg16 = (u16 *)reg32;
389 @@ -812,17 +827,28 @@ static const struct ethtool_ops ivshm_net_ethtool_ops = {
390 .get_regs = ivshm_net_get_regs,
393 +static u64 get_config_qword(struct pci_dev *pdev, unsigned int pos)
397 + pci_read_config_dword(pdev, pos, &lo);
398 + pci_read_config_dword(pdev, pos + 4, &hi);
399 + return lo | ((u64)hi << 32);
402 static int ivshm_net_probe(struct pci_dev *pdev,
403 - const struct pci_device_id *id)
404 + const struct pci_device_id *pci_id)
406 + phys_addr_t output_sections_addr, section_addr;
407 + resource_size_t section_sz, output_section_sz;
408 + void *state_table, *output_sections;
409 + struct ivshm_regs __iomem *regs;
410 struct net_device *ndev;
411 struct ivshm_net *in;
412 - struct ivshmem_regs __iomem *regs;
413 - resource_size_t shmaddr;
414 - resource_size_t shmlen;
415 + unsigned int cap_pos;
423 ret = pcim_enable_device(pdev);
424 @@ -839,40 +865,75 @@ static int ivshm_net_probe(struct pci_dev *pdev,
426 regs = pcim_iomap_table(pdev)[0];
428 - shmlen = pci_resource_len(pdev, 2);
429 + id = readl(®s->id);
431 + dev_err(&pdev->dev, "invalid ID %d\n", id);
434 + if (readl(®s->max_peers) > 2) {
435 + dev_err(&pdev->dev, "only 2 peers supported\n");
439 + vendor_cap = pci_find_capability(pdev, PCI_CAP_ID_VNDR);
440 + if (vendor_cap < 0) {
441 + dev_err(&pdev->dev, "missing vendor capability\n");
446 - shmaddr = pci_resource_start(pdev, 2);
447 + if (pci_resource_len(pdev, 2) > 0) {
448 + section_addr = pci_resource_start(pdev, 2);
450 - union { u64 v; u32 hl[2]; } val;
452 - pci_read_config_dword(pdev, JAILHOUSE_CFG_SHMEM_PTR,
454 - pci_read_config_dword(pdev, JAILHOUSE_CFG_SHMEM_PTR + 4,
458 - pci_read_config_dword(pdev, JAILHOUSE_CFG_SHMEM_SZ,
460 - pci_read_config_dword(pdev, JAILHOUSE_CFG_SHMEM_SZ + 4,
463 + cap_pos = vendor_cap + IVSHM_CFG_ADDRESS;
464 + section_addr = get_config_qword(pdev, cap_pos);
467 + cap_pos = vendor_cap + IVSHM_CFG_STATE_TAB_SZ;
468 + pci_read_config_dword(pdev, cap_pos, &dword);
469 + section_sz = dword;
471 - if (!devm_request_mem_region(&pdev->dev, shmaddr, shmlen, DRV_NAME))
472 + if (!devm_request_mem_region(&pdev->dev, section_addr, section_sz,
476 - shm = devm_memremap(&pdev->dev, shmaddr, shmlen, MEMREMAP_WB);
478 + state_table = devm_memremap(&pdev->dev, section_addr, section_sz,
483 - ivpos = readl(®s->ivpos);
485 - dev_err(&pdev->dev, "invalid IVPosition %d\n", ivpos);
486 + output_sections_addr = section_addr + section_sz;
488 + cap_pos = vendor_cap + IVSHM_CFG_RW_SECTION_SZ;
489 + section_sz = get_config_qword(pdev, cap_pos);
490 + if (section_sz > 0) {
491 + dev_info(&pdev->dev, "R/W section detected - "
492 + "unused by this driver version\n");
493 + output_sections_addr += section_sz;
496 + cap_pos = vendor_cap + IVSHM_CFG_OUTPUT_SECTION_SZ;
497 + output_section_sz = get_config_qword(pdev, cap_pos);
498 + if (output_section_sz == 0) {
499 + dev_err(&pdev->dev, "Missing input/output sections\n");
503 + if (!devm_request_mem_region(&pdev->dev, output_sections_addr,
504 + output_section_sz * 2, DRV_NAME))
507 + output_sections = devm_memremap(&pdev->dev, output_sections_addr,
508 + output_section_sz * 2, MEMREMAP_WB);
509 + if (!output_sections)
512 + section_addr = output_sections_addr + output_section_sz * id;
513 + dev_info(&pdev->dev, "TX memory at %pa, size %pa\n",
514 + §ion_addr, &output_section_sz);
515 + section_addr = output_sections_addr + output_section_sz * !id;
516 + dev_info(&pdev->dev, "RX memory at %pa, size %pa\n",
517 + §ion_addr, &output_section_sz);
519 device_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s[%s]", DRV_NAME,
520 dev_name(&pdev->dev));
522 @@ -887,10 +948,16 @@ static int ivshm_net_probe(struct pci_dev *pdev,
524 in = netdev_priv(ndev);
525 in->ivshm_regs = regs;
527 - in->shmaddr = shmaddr;
528 - in->shmlen = shmlen;
529 - in->peer_id = !ivpos;
530 + in->state_table = state_table;
532 + in->shm[IVSHM_NET_SECTION_TX] =
533 + output_sections + output_section_sz * id;
534 + in->shm[IVSHM_NET_SECTION_RX] =
535 + output_sections + output_section_sz * !id;
537 + in->shmlen = output_section_sz;
541 spin_lock_init(&in->tx_free_lock);
542 spin_lock_init(&in->tx_clean_lock);
543 @@ -919,24 +986,64 @@ static int ivshm_net_probe(struct pci_dev *pdev,
547 - ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_LEGACY | PCI_IRQ_MSIX);
548 + ret = pci_alloc_irq_vectors(pdev, 1, 2, PCI_IRQ_LEGACY | PCI_IRQ_MSIX);
552 - ret = request_irq(pci_irq_vector(pdev, 0), ivshm_net_int, 0,
553 - device_name, ndev);
555 - goto err_request_irq;
556 + if (pdev->msix_enabled) {
559 + goto err_request_irq;
562 + device_name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
563 + "%s-state[%s]", DRV_NAME,
564 + dev_name(&pdev->dev));
565 + if (!device_name) {
567 + goto err_request_irq;
570 + ret = request_irq(pci_irq_vector(pdev, IVSHM_NET_MSIX_STATE),
571 + ivshm_net_int_state, 0, device_name, in);
573 + goto err_request_irq;
575 + device_name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
576 + "%s-tx-rx[%s]", DRV_NAME,
577 + dev_name(&pdev->dev));
578 + if (!device_name) {
580 + goto err_request_irq2;
583 + ret = request_irq(pci_irq_vector(pdev, IVSHM_NET_MSIX_TX_RX),
584 + ivshm_net_int_tx_rx, 0, device_name, in);
586 + goto err_request_irq2;
588 + in->tx_rx_vector = IVSHM_NET_MSIX_TX_RX;
590 + ret = request_irq(pci_irq_vector(pdev, 0), ivshm_net_intx, 0,
593 + goto err_request_irq;
595 + in->tx_rx_vector = 0;
598 pci_set_master(pdev);
599 - if (!pdev->msix_enabled)
600 - writel(IVSHMEM_INTX_ENABLE, &in->ivshm_regs->intxctrl);
602 - writel(IVSHM_NET_STATE_RESET, &in->ivshm_regs->lstate);
603 - ivshm_net_check_state(ndev);
604 + pci_write_config_byte(pdev, vendor_cap + IVSHM_CFG_PRIV_CNTL, 0);
605 + writel(IVSHM_INT_ENABLE, &in->ivshm_regs->int_control);
607 + writel(IVSHM_NET_STATE_RESET, &in->ivshm_regs->state);
608 + ivshm_net_check_state(in);
613 + free_irq(pci_irq_vector(pdev, IVSHM_NET_MSIX_STATE), in);
615 pci_free_irq_vectors(pdev);
617 @@ -954,11 +1061,15 @@ static void ivshm_net_remove(struct pci_dev *pdev)
618 struct net_device *ndev = pci_get_drvdata(pdev);
619 struct ivshm_net *in = netdev_priv(ndev);
621 - writel(IVSHM_NET_STATE_RESET, &in->ivshm_regs->lstate);
622 + writel(IVSHM_NET_STATE_RESET, &in->ivshm_regs->state);
623 + writel(0, &in->ivshm_regs->int_control);
625 - if (!pdev->msix_enabled)
626 - writel(0, &in->ivshm_regs->intxctrl);
627 - free_irq(pci_irq_vector(pdev, 0), ndev);
628 + if (pdev->msix_enabled) {
629 + free_irq(pci_irq_vector(pdev, IVSHM_NET_MSIX_STATE), in);
630 + free_irq(pci_irq_vector(pdev, IVSHM_NET_MSIX_TX_RX), in);
632 + free_irq(pci_irq_vector(pdev, 0), in);
634 pci_free_irq_vectors(pdev);
636 unregister_netdev(ndev);
637 @@ -968,8 +1079,8 @@ static void ivshm_net_remove(struct pci_dev *pdev)
640 static const struct pci_device_id ivshm_net_id_table[] = {
641 - { PCI_DEVICE(PCI_VENDOR_ID_REDHAT_QUMRANET, 0x1110),
642 - (PCI_CLASS_OTHERS << 16) | (0x01 << 8), 0xffff00 },
643 + { PCI_DEVICE(PCI_VENDOR_ID_SIEMENS, PCI_DEVICE_ID_IVSHMEM),
644 + (PCI_CLASS_OTHERS << 16) | IVSHM_PROTO_NET, 0xffffff },
647 MODULE_DEVICE_TABLE(pci, ivshm_net_id_table);