Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH net-next] dpaa2-eth: Don't use netif_receive_skb_list for TCP frames
From: David Miller @ 2019-07-23 21:02 UTC (permalink / raw)
  To: ruxandra.radulescu; +Cc: netdev, ioana.ciornei, vladimir.oltean
In-Reply-To: <1563902923-26178-1-git-send-email-ruxandra.radulescu@nxp.com>

From: Ioana Radulescu <ruxandra.radulescu@nxp.com>
Date: Tue, 23 Jul 2019 20:28:43 +0300

> Using Rx skb bulking for all frames may negatively impact the
> performance in some TCP termination scenarios, as it effectively
> bypasses GRO.

"may"?

Please provide numbers so that we know exactly whether it actually
hurts performance one way or another.

Thank you.

^ permalink raw reply

* Re: [net-next 6/6] e1000e: disable force K1-off feature
From: David Miller @ 2019-07-23 21:04 UTC (permalink / raw)
  To: jeffrey.t.kirsher; +Cc: kai.heng.feng, netdev, nhorman, sassmann, aaron.f.brown
In-Reply-To: <20190723173650.23276-7-jeffrey.t.kirsher@intel.com>

From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Tue, 23 Jul 2019 10:36:50 -0700

> diff --git a/drivers/net/ethernet/intel/e1000e/hw.h b/drivers/net/ethernet/intel/e1000e/hw.h
> index eff75bd8a8f0..e3c71fd093ee 100644
> --- a/drivers/net/ethernet/intel/e1000e/hw.h
> +++ b/drivers/net/ethernet/intel/e1000e/hw.h
> @@ -662,6 +662,7 @@ struct e1000_dev_spec_ich8lan {
>  	bool kmrn_lock_loss_workaround_enabled;
>  	struct e1000_shadow_ram shadow_ram[E1000_ICH8_SHADOW_RAM_WORDS];
>  	bool nvm_k1_enabled;
> +	bool disable_k1_off;
>  	bool eee_disable;

I don't see any code actually setting this boolean, how does it work?

^ permalink raw reply

* Re: [PATCH bpf v3] bpf: fix narrower loads on s390
From: Alexei Starovoitov @ 2019-07-23 21:04 UTC (permalink / raw)
  To: Ilya Leoshkevich; +Cc: bpf, Network Development, Y Song, gor, Heiko Carstens
In-Reply-To: <20190719091815.92181-1-iii@linux.ibm.com>

On Fri, Jul 19, 2019 at 2:18 AM Ilya Leoshkevich <iii@linux.ibm.com> wrote:
>
> The very first check in test_pkt_md_access is failing on s390, which
> happens because loading a part of a struct __sk_buff field produces
> an incorrect result.
>
> The preprocessed code of the check is:
>
> {
>         __u8 tmp = *((volatile __u8 *)&skb->len +
>                 ((sizeof(skb->len) - sizeof(__u8)) / sizeof(__u8)));
>         if (tmp != ((*(volatile __u32 *)&skb->len) & 0xFF)) return 2;
> };
>
> clang generates the following code for it:
>
>       0:        71 21 00 03 00 00 00 00 r2 = *(u8 *)(r1 + 3)
>       1:        61 31 00 00 00 00 00 00 r3 = *(u32 *)(r1 + 0)
>       2:        57 30 00 00 00 00 00 ff r3 &= 255
>       3:        5d 23 00 1d 00 00 00 00 if r2 != r3 goto +29 <LBB0_10>
>
> Finally, verifier transforms it to:
>
>   0: (61) r2 = *(u32 *)(r1 +104)
>   1: (bc) w2 = w2
>   2: (74) w2 >>= 24
>   3: (bc) w2 = w2
>   4: (54) w2 &= 255
>   5: (bc) w2 = w2
>
> The problem is that when verifier emits the code to replace a partial
> load of a struct __sk_buff field (*(u8 *)(r1 + 3)) with a full load of
> struct sk_buff field (*(u32 *)(r1 + 104)), an optional shift and a
> bitwise AND, it assumes that the machine is little endian and
> incorrectly decides to use a shift.
>
> Adjust shift count calculation to account for endianness.
>
> Fixes: 31fd85816dbe ("bpf: permits narrower load from bpf program context fields")
> Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>

Applied to bpf tree. Thanks

^ permalink raw reply

* Re: [PATCH v2] drivers: net: xgene: Remove acpi_has_method() calls
From: David Miller @ 2019-07-23 21:06 UTC (permalink / raw)
  To: skunberg.kelsey
  Cc: iyappan, keyur, quan, netdev, linux-kernel, bjorn, skhan,
	linux-kernel-mentees
In-Reply-To: <20190723185811.8548-1-skunberg.kelsey@gmail.com>

From: Kelsey Skunberg <skunberg.kelsey@gmail.com>
Date: Tue, 23 Jul 2019 12:58:11 -0600

> acpi_evaluate_object will already return an error if the needed method
> does not exist. Remove unnecessary acpi_has_method() calls and check the
> returned acpi_status for failure instead.
> 
> Signed-off-by: Kelsey Skunberg <skunberg.kelsey@gmail.com>
> ---
> Changes in v2:
> 	- Fixed white space warnings and errors

Applied to net-next.

^ permalink raw reply

* Re: [PATCH v2] drivers: net: xgene: Remove acpi_has_method() calls
From: David Miller @ 2019-07-23 21:07 UTC (permalink / raw)
  To: skunberg.kelsey
  Cc: iyappan, keyur, quan, netdev, linux-kernel, bjorn, skhan,
	linux-kernel-mentees
In-Reply-To: <20190723.140646.505566792140054611.davem@davemloft.net>

From: David Miller <davem@davemloft.net>
Date: Tue, 23 Jul 2019 14:06:46 -0700 (PDT)

> From: Kelsey Skunberg <skunberg.kelsey@gmail.com>
> Date: Tue, 23 Jul 2019 12:58:11 -0600
> 
>> acpi_evaluate_object will already return an error if the needed method
>> does not exist. Remove unnecessary acpi_has_method() calls and check the
>> returned acpi_status for failure instead.
>> 
>> Signed-off-by: Kelsey Skunberg <skunberg.kelsey@gmail.com>
>> ---
>> Changes in v2:
>> 	- Fixed white space warnings and errors
> 
> Applied to net-next.

Wow did you even build test this?   Reverted...

drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c: In function ‘xgene_enet_reset’:
drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c:480:13: error: invalid storage class for function ‘xgene_enet_cle_bypass’
 static void xgene_enet_cle_bypass(struct xgene_enet_pdata *p,
             ^~~~~~~~~~~~~~~~~~~~~
drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c:480:1: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
 static void xgene_enet_cle_bypass(struct xgene_enet_pdata *p,
 ^~~~~~
drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c:506:13: error: invalid storage class for function ‘xgene_enet_clear’
 static void xgene_enet_clear(struct xgene_enet_pdata *pdata,
             ^~~~~~~~~~~~~~~~
drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c:522:13: error: invalid storage class for function ‘xgene_enet_shutdown’
 static void xgene_enet_shutdown(struct xgene_enet_pdata *p)
             ^~~~~~~~~~~~~~~~~~~
drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c:532:13: error: invalid storage class for function ‘xgene_enet_link_state’
 static void xgene_enet_link_state(struct work_struct *work)
             ^~~~~~~~~~~~~~~~~~~~~
drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c:563:13: error: invalid storage class for function ‘xgene_sgmac_enable_tx_pause’
 static void xgene_sgmac_enable_tx_pause(struct xgene_enet_pdata *p, bool enable)
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c:604:1: error: expected declaration or statement at end of input
 };
 ^
drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c:599:29: warning: unused variable ‘xgene_sgport_ops’ [-Wunused-variable]
 const struct xgene_port_ops xgene_sgport_ops = {
                             ^~~~~~~~~~~~~~~~
drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c:582:28: warning: unused variable ‘xgene_sgmac_ops’ [-Wunused-variable]
 const struct xgene_mac_ops xgene_sgmac_ops = {
                            ^~~~~~~~~~~~~~~
At top level:
drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c:437:12: warning: ‘xgene_enet_reset’ defined but not used [-Wunused-function]
 static int xgene_enet_reset(struct xgene_enet_pdata *p)
            ^~~~~~~~~~~~~~~~

^ permalink raw reply

* Re: [PATCH v2 00/10] XDP unaligned chunk placement support
From: Alexei Starovoitov @ 2019-07-23 21:08 UTC (permalink / raw)
  To: Kevin Laatz
  Cc: Network Development, Alexei Starovoitov, Daniel Borkmann,
	Björn Töpel, Karlsson, Magnus, Jakub Kicinski,
	Jonathan Lemon, bruce.richardson, ciara.loftus, bpf,
	intel-wired-lan
In-Reply-To: <20190716030637.5634-1-kevin.laatz@intel.com>

Johnathan, Bjorn, Jakub,
Please review!
The patch set has been pending for a week.

On Tue, Jul 16, 2019 at 4:21 AM Kevin Laatz <kevin.laatz@intel.com> wrote:
>
> This patch set adds the ability to use unaligned chunks in the XDP umem.
>
> Currently, all chunk addresses passed to the umem are masked to be chunk
> size aligned (default is 2k, max is PAGE_SIZE). This limits where we can
> place chunks within the umem as well as limiting the packet sizes that are
> supported.
>
> The changes in this patch set removes these restrictions, allowing XDP to
> be more flexible in where it can place a chunk within a umem. By relaxing
> where the chunks can be placed, it allows us to use an arbitrary buffer
> size and place that wherever we have a free address in the umem. These
> changes add the ability to support arbitrary frame sizes up to 4k
> (PAGE_SIZE) and make it easy to integrate with other existing frameworks
> that have their own memory management systems, such as DPDK.
>
> Since we are now dealing with arbitrary frame sizes, we need also need to
> update how we pass around addresses. Currently, the addresses can simply be
> masked to 2k to get back to the original address. This becomes less trivial
> when using frame sizes that are not a 'power of 2' size. This patch set
> modifies the Rx/Tx descriptor format to use the upper 16-bits of the addr
> field for an offset value, leaving the lower 48-bits for the address (this
> leaves us with 256 Terabytes, which should be enough!). We only need to use
> the upper 16-bits to store the offset when running in unaligned mode.
> Rather than adding the offset (headroom etc) to the address, we will store
> it in the upper 16-bits of the address field. This way, we can easily add
> the offset to the address where we need it, using some bit manipulation and
> addition, and we can also easily get the original address wherever we need
> it (for example in i40e_zca_free) by simply masking to get the lower
> 48-bits of the address field.
>
> The numbers below were recorded with the following set up:
>   - Intel(R) Xeon(R) Gold 6140 CPU @ 2.30GHz
>   - Intel Corporation Ethernet Controller XXV710 for 25GbE SFP28 (rev 02)
>   - Driver: i40e
>   - Application: xdpsock with l2fwd (single interface)
>
> These are solely for comparing performance with and without the patches.
> The largest drop was ~1% (in zero-copy mode).
>
> +-------------------------+------------+-----------------+-------------+
> | Buffer size: 2048       | SKB mode   | Zero-copy       | Copy        |
> +-------------------------+------------+-----------------+-------------+
> | Aligned (baseline)      | 1.7 Mpps   | 15.3 Mpps       | 2.08 Mpps   |
> +-------------------------+------------+-----------------+-------------+
> | Aligned (with patches)  | 1.7 Mpps   | 15.1 Mpps       | 2.08 Mpps   |
> +-------------------------+------------+-----------------+-------------+
> | Unaligned               | 1.7 Mpps   | 14.5 Mpps       | 2.08 Mpps   |
> +-------------------------+------------+-----------------+-------------+
>
> NOTE: We are currently working on the changes required in the Mellanox
> driver. We will include these in the v3.
>
> Structure of the patchset:
> Patch 1:
>   - Remove unnecessary masking and headroom addition during zero-copy Rx
>     buffer recycling in i40e. This change is required in order for the
>     buffer recycling to work in the unaligned chunk mode.
>
> Patch 2:
>   - Remove unnecessary masking and headroom addition during
>     zero-copy Rx buffer recycling in ixgbe. This change is required in
>     order for the  buffer recycling to work in the unaligned chunk mode.
>
> Patch 3:
>   - Add infrastructure for unaligned chunks. Since we are dealing with
>     unaligned chunks that could potentially cross a physical page boundary,
>     we add checks to keep track of that information. We can later use this
>     information to correctly handle buffers that are placed at an address
>     where they cross a page boundary.  This patch also modifies the
>     existing Rx and Tx functions to use the new descriptor format. To
>     handle addresses correctly, we need to mask appropriately based on
>     whether we are in aligned or unaligned mode.
>
> Patch 4:
>   - This patch updates the i40e driver to make use of the new descriptor
>     format. The new format is particularly useful here since we can now
>     retrieve the original address in places like i40e_zca_free with ease.
>     This saves us doing various calculations to get the original address
>     back.
>
> Patch 5:
>   - This patch updates the ixgbe driver to make use of the new descriptor
>     format. The new format is particularly useful here since we can now
>     retrieve the original address in places like ixgbe_zca_free with ease.
>     This saves us doing various calculations to get the original address
>     back.
>
> Patch 6:
>   - Add flags for umem configuration to libbpf
>
> Patch 7:
>   - Modify xdpsock application to add a command line option for
>     unaligned chunks
>
> Patch 8:
>   - Since we can now run the application in unaligned chunk mode, we need
>     to make sure we recycle the buffers appropriately.
>
> Patch 9:
>   - Adds hugepage support to the xdpsock application
>
> Patch 10:
>   - Documentation update to include the unaligned chunk scenario. We need
>     to explicitly state that the incoming addresses are only masked in the
>     aligned chunk mode and not the unaligned chunk mode.
>
> ---
> v2:
>   - fixed checkpatch issues
>   - fixed Rx buffer recycling for unaligned chunks in xdpsock
>   - removed unused defines
>   - fixed how chunk_size is calculated in xsk_diag.c
>   - added some performance numbers to cover letter
>   - modified descriptor format to make it easier to retrieve original
>     address
>   - removed patch adding off_t off to the zero copy allocator. This is no
>     longer needed with the new descriptor format.
>
> Kevin Laatz (10):
>   i40e: simplify Rx buffer recycle
>   ixgbe: simplify Rx buffer recycle
>   xsk: add support to allow unaligned chunk placement
>   i40e: modify driver for handling offsets
>   ixgbe: modify driver for handling offsets
>   libbpf: add flags to umem config
>   samples/bpf: add unaligned chunks mode support to xdpsock
>   samples/bpf: add buffer recycling for unaligned chunks to xdpsock
>   samples/bpf: use hugepages in xdpsock app
>   doc/af_xdp: include unaligned chunk case
>
>  Documentation/networking/af_xdp.rst          | 10 ++-
>  drivers/net/ethernet/intel/i40e/i40e_xsk.c   | 39 +++++----
>  drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c | 39 +++++----
>  include/net/xdp_sock.h                       |  2 +
>  include/uapi/linux/if_xdp.h                  |  9 ++
>  net/xdp/xdp_umem.c                           | 17 ++--
>  net/xdp/xsk.c                                | 89 ++++++++++++++++----
>  net/xdp/xsk_diag.c                           |  2 +-
>  net/xdp/xsk_queue.h                          | 70 +++++++++++++--
>  samples/bpf/xdpsock_user.c                   | 61 ++++++++++----
>  tools/include/uapi/linux/if_xdp.h            |  4 +
>  tools/lib/bpf/xsk.c                          |  3 +
>  tools/lib/bpf/xsk.h                          |  2 +
>  13 files changed, 266 insertions(+), 81 deletions(-)
>
> --
> 2.17.1
>

^ permalink raw reply

* Re: [PATCH net-next 1/1] tc-testing: added tdc tests for [b|p]fifo qdisc
From: David Miller @ 2019-07-23 21:08 UTC (permalink / raw)
  To: mrv; +Cc: netdev, kernel, jhs, xiyou.wangcong, jiri
In-Reply-To: <1563908519-30111-1-git-send-email-mrv@mojatatu.com>

From: Roman Mashak <mrv@mojatatu.com>
Date: Tue, 23 Jul 2019 15:01:59 -0400

> Signed-off-by: Roman Mashak <mrv@mojatatu.com>

Always love to see new tests...  Applied.

^ permalink raw reply

* Re: [PATCH v1] net: thunderx: Use fwnode_get_mac_address()
From: David Miller @ 2019-07-23 21:09 UTC (permalink / raw)
  To: andriy.shevchenko; +Cc: sgoutham, rric, linux-arm-kernel, netdev
In-Reply-To: <20190723200344.69864-1-andriy.shevchenko@linux.intel.com>

From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Date: Tue, 23 Jul 2019 23:03:43 +0300

> Replace the custom implementation with fwnode_get_mac_address,
> which works on both DT and ACPI platforms.
> 
> While here, replace memcpy() by ether_addr_copy().
> 
> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

Applied.

^ permalink raw reply

* [PATCH v2 bpf-next] libbpf: provide more helpful message on uninitialized global var
From: Andrii Nakryiko @ 2019-07-23 21:11 UTC (permalink / raw)
  To: bpf, netdev, ast, daniel, songliubraving
  Cc: andrii.nakryiko, kernel-team, Andrii Nakryiko

When BPF program defines uninitialized global variable, it's put into
a special COMMON section. Libbpf will reject such programs, but will
provide very unhelpful message with garbage-looking section index.

This patch detects special section cases and gives more explicit error
message.

Signed-off-by: Andrii Nakryiko <andriin@fb.com>
---
 tools/lib/bpf/libbpf.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 794dd5064ae8..8741c39adb1c 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -1760,15 +1760,22 @@ bpf_program__collect_reloc(struct bpf_program *prog, GElf_Shdr *shdr,
 			 (long long) sym.st_value, sym.st_name, name);
 
 		shdr_idx = sym.st_shndx;
+		insn_idx = rel.r_offset / sizeof(struct bpf_insn);
+		pr_debug("relocation: insn_idx=%u, shdr_idx=%u\n",
+			 insn_idx, shdr_idx);
+
+		if (shdr_idx >= SHN_LORESERVE) {
+			pr_warning("relocation: not yet supported relo for non-static global \'%s\' variable in special section (0x%x) found in insns[%d].code 0x%x\n",
+				   name, shdr_idx, insn_idx,
+				   insns[insn_idx].code);
+			return -LIBBPF_ERRNO__RELOC;
+		}
 		if (!bpf_object__relo_in_known_section(obj, shdr_idx)) {
 			pr_warning("Program '%s' contains unrecognized relo data pointing to section %u\n",
 				   prog->section_name, shdr_idx);
 			return -LIBBPF_ERRNO__RELOC;
 		}
 
-		insn_idx = rel.r_offset / sizeof(struct bpf_insn);
-		pr_debug("relocation: insn_idx=%u\n", insn_idx);
-
 		if (insns[insn_idx].code == (BPF_JMP | BPF_CALL)) {
 			if (insns[insn_idx].src_reg != BPF_PSEUDO_CALL) {
 				pr_warning("incorrect bpf_call opcode\n");
-- 
2.17.1


^ permalink raw reply related

* Re: [PATCH bpf 0/2] bpf: gso_segs fixes
From: Alexei Starovoitov @ 2019-07-23 21:15 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Alexei Starovoitov, Daniel Borkmann, David S . Miller, netdev,
	Eric Dumazet, Stanislav Fomichev, bpf
In-Reply-To: <20190723101538.136328-1-edumazet@google.com>

On Tue, Jul 23, 2019 at 3:15 AM Eric Dumazet <edumazet@google.com> wrote:
>
> First patch changes the kernel, second patch
> adds a new test.
>
> Note that other patches might be needed to take
> care of similar issues in sock_ops_convert_ctx_access()
> and SOCK_OPS_GET_FIELD()

Nice catch!
Applied to bpf tree. Thanks

^ permalink raw reply

* Re: [net-next 0/6][pull request] 1GbE Intel Wired LAN Driver Updates 2019-07-23
From: Saeed Mahameed @ 2019-07-23 21:16 UTC (permalink / raw)
  To: jeffrey.t.kirsher@intel.com, davem@davemloft.net
  Cc: nhorman@redhat.com, sassmann@redhat.com, netdev@vger.kernel.org
In-Reply-To: <20190723173650.23276-1-jeffrey.t.kirsher@intel.com>

On Tue, 2019-07-23 at 10:36 -0700, Jeff Kirsher wrote:
> This series contains updates to igc and e1000e client drivers only.
> 
> Sasha provides a couple of cleanups to remove code that is not needed
> and reduce structure sizes.  Updated the MAC reset flow to use the
> device reset flow instead of a port reset flow.  Added addition
> device
> id's that will be supported.
> 
> Kai-Heng Feng provides a workaround for a possible stalled packet
> issue
> in our ICH devices due to a clock recovery from the PCH being too
> slow.
> Also provided a fix where the MAC & PHY may become de-sync'd causing
> a
> miss detection of link up events.

For what it's worth, Series LGTM.


^ permalink raw reply

* Re: [PATCH v4 net-next 02/19] ionic: Add hardware init and device commands
From: David Miller @ 2019-07-23 21:18 UTC (permalink / raw)
  To: snelson; +Cc: netdev
In-Reply-To: <20190722214023.9513-3-snelson@pensando.io>

From: Shannon Nelson <snelson@pensando.io>
Date: Mon, 22 Jul 2019 14:40:06 -0700

> +void ionic_init_devinfo(struct ionic_dev *idev)
> +{
> +	idev->dev_info.asic_type = ioread8(&idev->dev_info_regs->asic_type);
> +	idev->dev_info.asic_rev = ioread8(&idev->dev_info_regs->asic_rev);
> +
> +	memcpy_fromio(idev->dev_info.fw_version,
> +		      idev->dev_info_regs->fw_version,
> +		      IONIC_DEVINFO_FWVERS_BUFLEN);
> +
> +	memcpy_fromio(idev->dev_info.serial_num,
> +		      idev->dev_info_regs->serial_num,
> +		      IONIC_DEVINFO_SERIAL_BUFLEN);
 ...
> +	sig = ioread32(&idev->dev_info_regs->signature);

I think if you are going to use the io{read,write}{8,16,32,64}()
interfaces then you should use io{read,write}{8,16,32,64}_rep()
instead of memcpy_{to,from}io().


^ permalink raw reply

* Re: [PATCH v4 net-next 05/19] ionic: Add interrupts and doorbells
From: David Miller @ 2019-07-23 21:24 UTC (permalink / raw)
  To: snelson; +Cc: netdev
In-Reply-To: <20190722214023.9513-6-snelson@pensando.io>

From: Shannon Nelson <snelson@pensando.io>
Date: Mon, 22 Jul 2019 14:40:09 -0700

> The ionic interrupt model is based on interrupt control blocks
> accessed through the PCI BAR.  Doorbell registers are used by
> the driver to signal to the NIC that requests are waiting on
> the message queues.  Interrupts are used by the NIC to signal
> to the driver that answers are waiting on the completion queues.
> 
> Signed-off-by: Shannon Nelson <snelson@pensando.io>

After applying this patch we get a warning:

drivers/net/ethernet/pensando/ionic/ionic_lif.c:33:13: warning: ‘ionic_intr_free’ defined but not used [-Wunused-function]
 static void ionic_intr_free(struct lif *lif, int index)
             ^~~~~~~~~~~~~~~
drivers/net/ethernet/pensando/ionic/ionic_lif.c:15:12: warning: ‘ionic_intr_alloc’ defined but not used [-Wunused-function]
 static int ionic_intr_alloc(struct lif *lif, struct intr *intr)
            ^~~~~~~~~~~~~~~~

Also:

> +	lif->dbid_inuse = kzalloc(BITS_TO_LONGS(lif->dbid_count) * sizeof(long),
> +				  GFP_KERNEL);

You can use bitmap_alloc() and friends from linux/bitmap.h for this kind of stuff.

^ permalink raw reply

* Re: [PATCH v4 net-next 06/19] ionic: Add basic adminq support
From: David Miller @ 2019-07-23 21:27 UTC (permalink / raw)
  To: snelson; +Cc: netdev
In-Reply-To: <20190722214023.9513-7-snelson@pensando.io>

From: Shannon Nelson <snelson@pensando.io>
Date: Mon, 22 Jul 2019 14:40:10 -0700

> +struct queue {
 ...
> +struct cq {
 ...
> +struct napi_stats {
 ...
> +struct q_stats {
 ...
> +struct qcq {

Using names like these and "dev_queue" are just asking for conflicts with the
global datastructure namespace both now and in the future.

Please put ionic_ or similar as a prefix to these data structure names.

Thank you.

^ permalink raw reply

* Re: [PATCH v4 net-next 11/19] ionic: Add Rx filter and rx_mode ndo support
From: David Miller @ 2019-07-23 21:33 UTC (permalink / raw)
  To: snelson; +Cc: netdev
In-Reply-To: <20190722214023.9513-12-snelson@pensando.io>

From: Shannon Nelson <snelson@pensando.io>
Date: Mon, 22 Jul 2019 14:40:15 -0700

> +	if (in_interrupt()) {
> +		work = kzalloc(sizeof(*work), GFP_ATOMIC);
> +		if (!work) {
> +			netdev_err(lif->netdev, "%s OOM\n", __func__);
> +			return -ENOMEM;
> +		}
> +		work->type = add ? DW_TYPE_RX_ADDR_ADD : DW_TYPE_RX_ADDR_DEL;
> +		memcpy(work->addr, addr, ETH_ALEN);
> +		netdev_dbg(lif->netdev, "deferred: rx_filter %s %pM\n",
> +			   add ? "add" : "del", addr);
> +		ionic_lif_deferred_enqueue(&lif->deferred, work);
> +	} else {
> +		netdev_dbg(lif->netdev, "rx_filter %s %pM\n",
> +			   add ? "add" : "del", addr);
> +		if (add)
> +			return ionic_lif_addr_add(lif, addr);
> +		else
> +			return ionic_lif_addr_del(lif, addr);
> +	}

I don't know about this.

Generally interface address changes are expected to be synchronous.

^ permalink raw reply

* Re: [PATCH iproute2] etf: make printing of variable JSON friendly
From: Patel, Vedang @ 2019-07-23 21:34 UTC (permalink / raw)
  To: David Ahern
  Cc: netdev@vger.kernel.org, Jamal Hadi Salim, Cong Wang, Jiri Pirko,
	Stephen Hemminger, Gomes, Vinicius, Dorileo, Leandro
In-Reply-To: <0e5fc2fe-dc83-b876-40ac-3b6f3f47bb29@gmail.com>



> On Jul 22, 2019, at 5:11 PM, David Ahern <dsahern@gmail.com> wrote:
> 
> On 7/22/19 1:11 PM, Patel, Vedang wrote:
>> 
>> 
>>> On Jul 22, 2019, at 11:21 AM, David Ahern <dsahern@gmail.com> wrote:
>>> 
>>> On 7/19/19 3:40 PM, Vedang Patel wrote:
>>>> In iproute2 txtime-assist series, it was pointed out that print_bool()
>>>> should be used to print binary values. This is to make it JSON friendly.
>>>> 
>>>> So, make the corresponding changes in ETF.
>>>> 
>>>> Fixes: 8ccd49383cdc ("etf: Add skip_sock_check")
>>>> Reported-by: Stephen Hemminger <stephen@networkplumber.org>
>>>> Signed-off-by: Vedang Patel <vedang.patel@intel.com>
>>>> ---
>>>> tc/q_etf.c | 12 ++++++------
>>>> 1 file changed, 6 insertions(+), 6 deletions(-)
>>>> 
>>>> diff --git a/tc/q_etf.c b/tc/q_etf.c
>>>> index c2090589bc64..307c50eed48b 100644
>>>> --- a/tc/q_etf.c
>>>> +++ b/tc/q_etf.c
>>>> @@ -176,12 +176,12 @@ static int etf_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
>>>> 		     get_clock_name(qopt->clockid));
>>>> 
>>>> 	print_uint(PRINT_ANY, "delta", "delta %d ", qopt->delta);
>>>> -	print_string(PRINT_ANY, "offload", "offload %s ",
>>>> -				(qopt->flags & TC_ETF_OFFLOAD_ON) ? "on" : "off");
>>>> -	print_string(PRINT_ANY, "deadline_mode", "deadline_mode %s ",
>>>> -				(qopt->flags & TC_ETF_DEADLINE_MODE_ON) ? "on" : "off");
>>>> -	print_string(PRINT_ANY, "skip_sock_check", "skip_sock_check %s",
>>>> -				(qopt->flags & TC_ETF_SKIP_SOCK_CHECK) ? "on" : "off");
>>>> +	if (qopt->flags & TC_ETF_OFFLOAD_ON)
>>>> +		print_bool(PRINT_ANY, "offload", "offload ", true);
>>>> +	if (qopt->flags & TC_ETF_DEADLINE_MODE_ON)
>>>> +		print_bool(PRINT_ANY, "deadline_mode", "deadline_mode ", true);
>>>> +	if (qopt->flags & TC_ETF_SKIP_SOCK_CHECK)
>>>> +		print_bool(PRINT_ANY, "skip_sock_check", "skip_sock_check", true);
>>>> 
>>>> 	return 0;
>>>> }
>>>> 
>>> 
>>> This changes existing output for TC_ETF_OFFLOAD_ON and
>>> TC_ETF_DEADLINE_MODE_ON which were added a year ago.
>> Yes, this is a good point. I missed that. 
>> 
>> Another idea is to use is_json_context() and call print_bool() there. But, that will still change values corresponding to the json output for the above flags from “on”/“off” to “true”/“false”. I am not sure if this is a big issue. 
>> 
>> My suggestion is to keep the code as is. what do you think?
>> 
> 
> I think we need automated checkers for new code. ;-)
> 
> The first 2 should not change for backward compatibility - unless there
> is agreement that this feature is too new and long term it is better to
> print as above.
> 
> Then the new one should follow context of the other 2 - consistency IMHO
> takes precedence.
Thanks for the inputs. 

Let’s keep whatever is currently present upstream and you can ignore this patch.

Thanks,
Vedang

^ permalink raw reply

* [PATCH v2 bpf-next 0/5] switch samples and tests to libbpf perf buffer API
From: Andrii Nakryiko @ 2019-07-23 21:34 UTC (permalink / raw)
  To: bpf, netdev, ast, daniel, songliubraving
  Cc: andrii.nakryiko, kernel-team, Andrii Nakryiko

There were few more tests and samples that were using custom perf buffer setup
code from trace_helpers.h. This patch set gets rid of all the usages of those
and removes helpers themselves. Libbpf provides nicer, but equally powerful
set of APIs to work with perf ring buffers, so let's have all the samples use

v1->v2:
- make logging message one long line instead of two (Song).

Andrii Nakryiko (5):
  selftests/bpf: convert test_get_stack_raw_tp to perf_buffer API
  selftests/bpf: switch test_tcpnotify to perf_buffer API
  samples/bpf: convert xdp_sample_pkts_user to perf_buffer API
  samples/bpf: switch trace_output sample to perf_buffer API
  selftests/bpf: remove perf buffer helpers

 samples/bpf/trace_output_user.c               |  43 ++----
 samples/bpf/xdp_sample_pkts_user.c            |  61 +++------
 .../bpf/prog_tests/get_stack_raw_tp.c         |  78 ++++++-----
 .../bpf/progs/test_get_stack_rawtp.c          |   2 +-
 .../selftests/bpf/test_tcpnotify_user.c       |  90 +++++--------
 tools/testing/selftests/bpf/trace_helpers.c   | 125 ------------------
 tools/testing/selftests/bpf/trace_helpers.h   |   9 --
 7 files changed, 111 insertions(+), 297 deletions(-)

-- 
2.17.1


^ permalink raw reply

* [PATCH v2 bpf-next 1/5] selftests/bpf: convert test_get_stack_raw_tp to perf_buffer API
From: Andrii Nakryiko @ 2019-07-23 21:34 UTC (permalink / raw)
  To: bpf, netdev, ast, daniel, songliubraving
  Cc: andrii.nakryiko, kernel-team, Andrii Nakryiko
In-Reply-To: <20190723213445.1732339-1-andriin@fb.com>

Convert test_get_stack_raw_tp test to new perf_buffer API.

Signed-off-by: Andrii Nakryiko <andriin@fb.com>
---
 .../bpf/prog_tests/get_stack_raw_tp.c         | 78 ++++++++++---------
 .../bpf/progs/test_get_stack_rawtp.c          |  2 +-
 2 files changed, 44 insertions(+), 36 deletions(-)

diff --git a/tools/testing/selftests/bpf/prog_tests/get_stack_raw_tp.c b/tools/testing/selftests/bpf/prog_tests/get_stack_raw_tp.c
index c2a0a9d5591b..9d73a8f932ac 100644
--- a/tools/testing/selftests/bpf/prog_tests/get_stack_raw_tp.c
+++ b/tools/testing/selftests/bpf/prog_tests/get_stack_raw_tp.c
@@ -1,8 +1,15 @@
 // SPDX-License-Identifier: GPL-2.0
+#define _GNU_SOURCE
+#include <pthread.h>
+#include <sched.h>
+#include <sys/socket.h>
 #include <test_progs.h>
 
 #define MAX_CNT_RAWTP	10ull
 #define MAX_STACK_RAWTP	100
+
+static int duration = 0;
+
 struct get_stack_trace_t {
 	int pid;
 	int kern_stack_size;
@@ -13,7 +20,7 @@ struct get_stack_trace_t {
 	struct bpf_stack_build_id user_stack_buildid[MAX_STACK_RAWTP];
 };
 
-static int get_stack_print_output(void *data, int size)
+static void get_stack_print_output(void *ctx, int cpu, void *data, __u32 size)
 {
 	bool good_kern_stack = false, good_user_stack = false;
 	const char *nonjit_func = "___bpf_prog_run";
@@ -65,75 +72,76 @@ static int get_stack_print_output(void *data, int size)
 		if (e->user_stack_size > 0 && e->user_stack_buildid_size > 0)
 			good_user_stack = true;
 	}
-	if (!good_kern_stack || !good_user_stack)
-		return LIBBPF_PERF_EVENT_ERROR;
 
-	if (cnt == MAX_CNT_RAWTP)
-		return LIBBPF_PERF_EVENT_DONE;
-
-	return LIBBPF_PERF_EVENT_CONT;
+	if (!good_kern_stack)
+	    CHECK(!good_kern_stack, "kern_stack", "corrupted kernel stack\n");
+	if (!good_user_stack)
+	    CHECK(!good_user_stack, "user_stack", "corrupted user stack\n");
 }
 
 void test_get_stack_raw_tp(void)
 {
 	const char *file = "./test_get_stack_rawtp.o";
-	int i, efd, err, prog_fd, pmu_fd, perfmap_fd;
-	struct perf_event_attr attr = {};
+	const char *prog_name = "raw_tracepoint/sys_enter";
+	int i, err, prog_fd, exp_cnt = MAX_CNT_RAWTP;
+	struct perf_buffer_opts pb_opts = {};
+	struct perf_buffer *pb = NULL;
+	struct bpf_link *link = NULL;
 	struct timespec tv = {0, 10};
-	__u32 key = 0, duration = 0;
+	struct bpf_program *prog;
 	struct bpf_object *obj;
+	struct bpf_map *map;
+	cpu_set_t cpu_set;
 
 	err = bpf_prog_load(file, BPF_PROG_TYPE_RAW_TRACEPOINT, &obj, &prog_fd);
 	if (CHECK(err, "prog_load raw tp", "err %d errno %d\n", err, errno))
 		return;
 
-	efd = bpf_raw_tracepoint_open("sys_enter", prog_fd);
-	if (CHECK(efd < 0, "raw_tp_open", "err %d errno %d\n", efd, errno))
+	prog = bpf_object__find_program_by_title(obj, prog_name);
+	if (CHECK(!prog, "find_probe", "prog '%s' not found\n", prog_name))
 		goto close_prog;
 
-	perfmap_fd = bpf_find_map(__func__, obj, "perfmap");
-	if (CHECK(perfmap_fd < 0, "bpf_find_map", "err %d errno %d\n",
-		  perfmap_fd, errno))
+	map = bpf_object__find_map_by_name(obj, "perfmap");
+	if (CHECK(!map, "bpf_find_map", "not found\n"))
 		goto close_prog;
 
 	err = load_kallsyms();
 	if (CHECK(err < 0, "load_kallsyms", "err %d errno %d\n", err, errno))
 		goto close_prog;
 
-	attr.sample_type = PERF_SAMPLE_RAW;
-	attr.type = PERF_TYPE_SOFTWARE;
-	attr.config = PERF_COUNT_SW_BPF_OUTPUT;
-	pmu_fd = syscall(__NR_perf_event_open, &attr, getpid()/*pid*/, -1/*cpu*/,
-			 -1/*group_fd*/, 0);
-	if (CHECK(pmu_fd < 0, "perf_event_open", "err %d errno %d\n", pmu_fd,
-		  errno))
+	CPU_ZERO(&cpu_set);
+	CPU_SET(0, &cpu_set);
+	err = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set), &cpu_set);
+	if (CHECK(err, "set_affinity", "err %d, errno %d\n", err, errno))
 		goto close_prog;
 
-	err = bpf_map_update_elem(perfmap_fd, &key, &pmu_fd, BPF_ANY);
-	if (CHECK(err < 0, "bpf_map_update_elem", "err %d errno %d\n", err,
-		  errno))
+	link = bpf_program__attach_raw_tracepoint(prog, "sys_enter");
+	if (CHECK(IS_ERR(link), "attach_raw_tp", "err %ld\n", PTR_ERR(link)))
 		goto close_prog;
 
-	err = ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0);
-	if (CHECK(err < 0, "ioctl PERF_EVENT_IOC_ENABLE", "err %d errno %d\n",
-		  err, errno))
-		goto close_prog;
-
-	err = perf_event_mmap(pmu_fd);
-	if (CHECK(err < 0, "perf_event_mmap", "err %d errno %d\n", err, errno))
+	pb_opts.sample_cb = get_stack_print_output;
+	pb = perf_buffer__new(bpf_map__fd(map), 8, &pb_opts);
+	if (CHECK(IS_ERR(pb), "perf_buf__new", "err %ld\n", PTR_ERR(pb)))
 		goto close_prog;
 
 	/* trigger some syscall action */
 	for (i = 0; i < MAX_CNT_RAWTP; i++)
 		nanosleep(&tv, NULL);
 
-	err = perf_event_poller(pmu_fd, get_stack_print_output);
-	if (CHECK(err < 0, "perf_event_poller", "err %d errno %d\n", err, errno))
-		goto close_prog;
+	while (exp_cnt > 0) {
+		err = perf_buffer__poll(pb, 100);
+		if (err < 0 && CHECK(err < 0, "pb__poll", "err %d\n", err))
+			goto close_prog;
+		exp_cnt -= err;
+	}
 
 	goto close_prog_noerr;
 close_prog:
 	error_cnt++;
 close_prog_noerr:
+	if (!IS_ERR_OR_NULL(link))
+		bpf_link__destroy(link);
+	if (!IS_ERR_OR_NULL(pb))
+		perf_buffer__free(pb);
 	bpf_object__close(obj);
 }
diff --git a/tools/testing/selftests/bpf/progs/test_get_stack_rawtp.c b/tools/testing/selftests/bpf/progs/test_get_stack_rawtp.c
index 33254b771384..f8ffa3f3d44b 100644
--- a/tools/testing/selftests/bpf/progs/test_get_stack_rawtp.c
+++ b/tools/testing/selftests/bpf/progs/test_get_stack_rawtp.c
@@ -55,7 +55,7 @@ struct {
 	__type(value, raw_stack_trace_t);
 } rawdata_map SEC(".maps");
 
-SEC("tracepoint/raw_syscalls/sys_enter")
+SEC("raw_tracepoint/sys_enter")
 int bpf_prog1(void *ctx)
 {
 	int max_len, max_buildid_len, usize, ksize, total_size;
-- 
2.17.1


^ permalink raw reply related

* [PATCH v2 bpf-next 2/5] selftests/bpf: switch test_tcpnotify to perf_buffer API
From: Andrii Nakryiko @ 2019-07-23 21:34 UTC (permalink / raw)
  To: bpf, netdev, ast, daniel, songliubraving
  Cc: andrii.nakryiko, kernel-team, Andrii Nakryiko
In-Reply-To: <20190723213445.1732339-1-andriin@fb.com>

Switch test_tcpnotify test to use libbpf's perf_buffer API instead of
re-implementing portion of it.

Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Acked-by: Song Liu <songliubraving@fb.com>
---
 .../selftests/bpf/test_tcpnotify_user.c       | 90 ++++++++-----------
 1 file changed, 36 insertions(+), 54 deletions(-)

diff --git a/tools/testing/selftests/bpf/test_tcpnotify_user.c b/tools/testing/selftests/bpf/test_tcpnotify_user.c
index 86152d9ae95b..f9765ddf0761 100644
--- a/tools/testing/selftests/bpf/test_tcpnotify_user.c
+++ b/tools/testing/selftests/bpf/test_tcpnotify_user.c
@@ -17,6 +17,7 @@
 #include <linux/rtnetlink.h>
 #include <signal.h>
 #include <linux/perf_event.h>
+#include <linux/err.h>
 
 #include "bpf_rlimit.h"
 #include "bpf_util.h"
@@ -30,28 +31,34 @@
 pthread_t tid;
 int rx_callbacks;
 
-static int dummyfn(void *data, int size)
+static void dummyfn(void *ctx, int cpu, void *data, __u32 size)
 {
 	struct tcp_notifier *t = data;
 
 	if (t->type != 0xde || t->subtype != 0xad ||
 	    t->source != 0xbe || t->hash != 0xef)
-		return 1;
+		return;
 	rx_callbacks++;
-	return 0;
 }
 
-void tcp_notifier_poller(int fd)
+void tcp_notifier_poller(struct perf_buffer *pb)
 {
-	while (1)
-		perf_event_poller(fd, dummyfn);
+	int err;
+
+	while (1) {
+		err = perf_buffer__poll(pb, 100);
+		if (err < 0 && err != -EINTR) {
+			printf("failed perf_buffer__poll: %d\n", err);
+			return;
+		}
+	}
 }
 
 static void *poller_thread(void *arg)
 {
-	int fd = *(int *)arg;
+	struct perf_buffer *pb = arg;
 
-	tcp_notifier_poller(fd);
+	tcp_notifier_poller(pb);
 	return arg;
 }
 
@@ -60,52 +67,20 @@ int verify_result(const struct tcpnotify_globals *result)
 	return (result->ncalls > 0 && result->ncalls == rx_callbacks ? 0 : 1);
 }
 
-static int bpf_find_map(const char *test, struct bpf_object *obj,
-			const char *name)
-{
-	struct bpf_map *map;
-
-	map = bpf_object__find_map_by_name(obj, name);
-	if (!map) {
-		printf("%s:FAIL:map '%s' not found\n", test, name);
-		return -1;
-	}
-	return bpf_map__fd(map);
-}
-
-static int setup_bpf_perf_event(int mapfd)
-{
-	struct perf_event_attr attr = {
-		.sample_type = PERF_SAMPLE_RAW,
-		.type = PERF_TYPE_SOFTWARE,
-		.config = PERF_COUNT_SW_BPF_OUTPUT,
-	};
-	int key = 0;
-	int pmu_fd;
-
-	pmu_fd = syscall(__NR_perf_event_open, &attr, -1, 0, -1, 0);
-	if (pmu_fd < 0)
-		return pmu_fd;
-	bpf_map_update_elem(mapfd, &key, &pmu_fd, BPF_ANY);
-
-	ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0);
-	return pmu_fd;
-}
-
 int main(int argc, char **argv)
 {
 	const char *file = "test_tcpnotify_kern.o";
-	int prog_fd, map_fd, perf_event_fd;
+	struct bpf_map *perf_map, *global_map;
+	struct perf_buffer_opts pb_opts = {};
 	struct tcpnotify_globals g = {0};
+	struct perf_buffer *pb = NULL;
 	const char *cg_path = "/foo";
+	int prog_fd, rv, cg_fd = -1;
 	int error = EXIT_FAILURE;
 	struct bpf_object *obj;
-	int cg_fd = -1;
-	__u32 key = 0;
-	int rv;
 	char test_script[80];
-	int pmu_fd;
 	cpu_set_t cpuset;
+	__u32 key = 0;
 
 	CPU_ZERO(&cpuset);
 	CPU_SET(0, &cpuset);
@@ -133,19 +108,24 @@ int main(int argc, char **argv)
 		goto err;
 	}
 
-	perf_event_fd = bpf_find_map(__func__, obj, "perf_event_map");
-	if (perf_event_fd < 0)
+	perf_map = bpf_object__find_map_by_name(obj, "perf_event_map");
+	if (!perf_map) {
+		printf("FAIL:map '%s' not found\n", "perf_event_map");
 		goto err;
+	}
 
-	map_fd = bpf_find_map(__func__, obj, "global_map");
-	if (map_fd < 0)
-		goto err;
+	global_map = bpf_object__find_map_by_name(obj, "global_map");
+	if (!global_map) {
+		printf("FAIL:map '%s' not found\n", "global_map");
+		return -1;
+	}
 
-	pmu_fd = setup_bpf_perf_event(perf_event_fd);
-	if (pmu_fd < 0 || perf_event_mmap(pmu_fd) < 0)
+	pb_opts.sample_cb = dummyfn;
+	pb = perf_buffer__new(bpf_map__fd(perf_map), 8, &pb_opts);
+	if (IS_ERR(pb))
 		goto err;
 
-	pthread_create(&tid, NULL, poller_thread, (void *)&pmu_fd);
+	pthread_create(&tid, NULL, poller_thread, pb);
 
 	sprintf(test_script,
 		"iptables -A INPUT -p tcp --dport %d -j DROP",
@@ -162,7 +142,7 @@ int main(int argc, char **argv)
 		TESTPORT);
 	system(test_script);
 
-	rv = bpf_map_lookup_elem(map_fd, &key, &g);
+	rv = bpf_map_lookup_elem(bpf_map__fd(global_map), &key, &g);
 	if (rv != 0) {
 		printf("FAILED: bpf_map_lookup_elem returns %d\n", rv);
 		goto err;
@@ -182,5 +162,7 @@ int main(int argc, char **argv)
 	bpf_prog_detach(cg_fd, BPF_CGROUP_SOCK_OPS);
 	close(cg_fd);
 	cleanup_cgroup_environment();
+	if (!IS_ERR_OR_NULL(pb))
+		perf_buffer__free(pb);
 	return error;
 }
-- 
2.17.1


^ permalink raw reply related

* Re: [PATCH v4 net-next 13/19] ionic: Add initial ethtool support
From: David Miller @ 2019-07-23 21:35 UTC (permalink / raw)
  To: snelson; +Cc: netdev
In-Reply-To: <20190722214023.9513-14-snelson@pensando.io>

From: Shannon Nelson <snelson@pensando.io>
Date: Mon, 22 Jul 2019 14:40:17 -0700

> +static int ionic_get_link_ksettings(struct net_device *netdev,
> +				    struct ethtool_link_ksettings *ks)
> +{
> +	struct lif *lif = netdev_priv(netdev);
> +	struct ionic_dev *idev = &lif->ionic->idev;
> +	int copper_seen = 0;

Reverse christmas tree ordering here please.

> +static int ionic_set_link_ksettings(struct net_device *netdev,
> +				    const struct ethtool_link_ksettings *ks)
> +{
> +	struct lif *lif = netdev_priv(netdev);
> +	struct ionic *ionic = lif->ionic;
> +	struct ionic_dev *idev = &lif->ionic->idev;
> +	u8 fec_type = PORT_FEC_TYPE_NONE;
> +	u32 req_rs, req_fc;
> +	int err = 0;

Likewise.
> +static void ionic_get_pauseparam(struct net_device *netdev,
> +				 struct ethtool_pauseparam *pause)
> +{
> +	struct lif *lif = netdev_priv(netdev);
> +	struct ionic_dev *idev = &lif->ionic->idev;
> +	uint8_t pause_type = idev->port_info->config.pause_type;

Likewise.

> +static int ionic_set_pauseparam(struct net_device *netdev,
> +				struct ethtool_pauseparam *pause)
> +{
> +	struct lif *lif = netdev_priv(netdev);
> +	struct ionic *ionic = lif->ionic;
> +	struct ionic_dev *idev = &lif->ionic->idev;
> +	u32 requested_pause;
> +	int err;

Likewise.
> +static int ionic_get_module_info(struct net_device *netdev,
> +				 struct ethtool_modinfo *modinfo)
> +
> +{
> +	struct lif *lif = netdev_priv(netdev);
> +	struct ionic_dev *idev = &lif->ionic->idev;
> +	struct xcvr_status *xcvr;

Likewise.

> +static int ionic_get_module_eeprom(struct net_device *netdev,
> +				   struct ethtool_eeprom *ee,
> +				   u8 *data)
> +{
> +	struct lif *lif = netdev_priv(netdev);
> +	struct ionic_dev *idev = &lif->ionic->idev;
> +	struct xcvr_status *xcvr;
> +	u32 len;

Likewise.

^ permalink raw reply

* [PATCH v2 bpf-next 5/5] selftests/bpf: remove perf buffer helpers
From: Andrii Nakryiko @ 2019-07-23 21:34 UTC (permalink / raw)
  To: bpf, netdev, ast, daniel, songliubraving
  Cc: andrii.nakryiko, kernel-team, Andrii Nakryiko
In-Reply-To: <20190723213445.1732339-1-andriin@fb.com>

libbpf's perf_buffer API supersedes trace_helper.h's helpers.
Remove those helpers after all existing users were already moved to
perf_buffer API.

Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Acked-by: Song Liu <songliubraving@fb.com>
---
 tools/testing/selftests/bpf/trace_helpers.c | 125 --------------------
 tools/testing/selftests/bpf/trace_helpers.h |   9 --
 2 files changed, 134 deletions(-)

diff --git a/tools/testing/selftests/bpf/trace_helpers.c b/tools/testing/selftests/bpf/trace_helpers.c
index b47f205f0310..7f989b3e4e22 100644
--- a/tools/testing/selftests/bpf/trace_helpers.c
+++ b/tools/testing/selftests/bpf/trace_helpers.c
@@ -86,128 +86,3 @@ long ksym_get_addr(const char *name)
 
 	return 0;
 }
-
-static int page_size;
-static int page_cnt = 8;
-static struct perf_event_mmap_page *header;
-
-int perf_event_mmap_header(int fd, struct perf_event_mmap_page **header)
-{
-	void *base;
-	int mmap_size;
-
-	page_size = getpagesize();
-	mmap_size = page_size * (page_cnt + 1);
-
-	base = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
-	if (base == MAP_FAILED) {
-		printf("mmap err\n");
-		return -1;
-	}
-
-	*header = base;
-	return 0;
-}
-
-int perf_event_mmap(int fd)
-{
-	return perf_event_mmap_header(fd, &header);
-}
-
-static int perf_event_poll(int fd)
-{
-	struct pollfd pfd = { .fd = fd, .events = POLLIN };
-
-	return poll(&pfd, 1, 1000);
-}
-
-struct perf_event_sample {
-	struct perf_event_header header;
-	__u32 size;
-	char data[];
-};
-
-static enum bpf_perf_event_ret
-bpf_perf_event_print(struct perf_event_header *hdr, void *private_data)
-{
-	struct perf_event_sample *e = (struct perf_event_sample *)hdr;
-	perf_event_print_fn fn = private_data;
-	int ret;
-
-	if (e->header.type == PERF_RECORD_SAMPLE) {
-		ret = fn(e->data, e->size);
-		if (ret != LIBBPF_PERF_EVENT_CONT)
-			return ret;
-	} else if (e->header.type == PERF_RECORD_LOST) {
-		struct {
-			struct perf_event_header header;
-			__u64 id;
-			__u64 lost;
-		} *lost = (void *) e;
-		printf("lost %lld events\n", lost->lost);
-	} else {
-		printf("unknown event type=%d size=%d\n",
-		       e->header.type, e->header.size);
-	}
-
-	return LIBBPF_PERF_EVENT_CONT;
-}
-
-int perf_event_poller(int fd, perf_event_print_fn output_fn)
-{
-	enum bpf_perf_event_ret ret;
-	void *buf = NULL;
-	size_t len = 0;
-
-	for (;;) {
-		perf_event_poll(fd);
-		ret = bpf_perf_event_read_simple(header, page_cnt * page_size,
-						 page_size, &buf, &len,
-						 bpf_perf_event_print,
-						 output_fn);
-		if (ret != LIBBPF_PERF_EVENT_CONT)
-			break;
-	}
-	free(buf);
-
-	return ret;
-}
-
-int perf_event_poller_multi(int *fds, struct perf_event_mmap_page **headers,
-			    int num_fds, perf_event_print_fn output_fn)
-{
-	enum bpf_perf_event_ret ret;
-	struct pollfd *pfds;
-	void *buf = NULL;
-	size_t len = 0;
-	int i;
-
-	pfds = calloc(num_fds, sizeof(*pfds));
-	if (!pfds)
-		return LIBBPF_PERF_EVENT_ERROR;
-
-	for (i = 0; i < num_fds; i++) {
-		pfds[i].fd = fds[i];
-		pfds[i].events = POLLIN;
-	}
-
-	for (;;) {
-		poll(pfds, num_fds, 1000);
-		for (i = 0; i < num_fds; i++) {
-			if (!pfds[i].revents)
-				continue;
-
-			ret = bpf_perf_event_read_simple(headers[i],
-							 page_cnt * page_size,
-							 page_size, &buf, &len,
-							 bpf_perf_event_print,
-							 output_fn);
-			if (ret != LIBBPF_PERF_EVENT_CONT)
-				break;
-		}
-	}
-	free(buf);
-	free(pfds);
-
-	return ret;
-}
diff --git a/tools/testing/selftests/bpf/trace_helpers.h b/tools/testing/selftests/bpf/trace_helpers.h
index 18924f23db1b..aa4dcfe18050 100644
--- a/tools/testing/selftests/bpf/trace_helpers.h
+++ b/tools/testing/selftests/bpf/trace_helpers.h
@@ -3,7 +3,6 @@
 #define __TRACE_HELPER_H
 
 #include <libbpf.h>
-#include <linux/perf_event.h>
 
 struct ksym {
 	long addr;
@@ -14,12 +13,4 @@ int load_kallsyms(void);
 struct ksym *ksym_search(long key);
 long ksym_get_addr(const char *name);
 
-typedef enum bpf_perf_event_ret (*perf_event_print_fn)(void *data, int size);
-
-int perf_event_mmap(int fd);
-int perf_event_mmap_header(int fd, struct perf_event_mmap_page **header);
-/* return LIBBPF_PERF_EVENT_DONE or LIBBPF_PERF_EVENT_ERROR */
-int perf_event_poller(int fd, perf_event_print_fn output_fn);
-int perf_event_poller_multi(int *fds, struct perf_event_mmap_page **headers,
-			    int num_fds, perf_event_print_fn output_fn);
 #endif
-- 
2.17.1


^ permalink raw reply related

* [PATCH v2 bpf-next 3/5] samples/bpf: convert xdp_sample_pkts_user to perf_buffer API
From: Andrii Nakryiko @ 2019-07-23 21:34 UTC (permalink / raw)
  To: bpf, netdev, ast, daniel, songliubraving
  Cc: andrii.nakryiko, kernel-team, Andrii Nakryiko
In-Reply-To: <20190723213445.1732339-1-andriin@fb.com>

Convert xdp_sample_pkts_user to libbpf's perf_buffer API.

Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Acked-by: Song Liu <songliubraving@fb.com>
Acked-by: Toke Høiland-Jørgensen <toke@redhat.com>
---
 samples/bpf/xdp_sample_pkts_user.c | 61 +++++++++---------------------
 1 file changed, 17 insertions(+), 44 deletions(-)

diff --git a/samples/bpf/xdp_sample_pkts_user.c b/samples/bpf/xdp_sample_pkts_user.c
index dc66345a929a..3002714e3cd5 100644
--- a/samples/bpf/xdp_sample_pkts_user.c
+++ b/samples/bpf/xdp_sample_pkts_user.c
@@ -17,14 +17,13 @@
 #include <linux/if_link.h>
 
 #include "perf-sys.h"
-#include "trace_helpers.h"
 
 #define MAX_CPUS 128
-static int pmu_fds[MAX_CPUS], if_idx;
-static struct perf_event_mmap_page *headers[MAX_CPUS];
+static int if_idx;
 static char *if_name;
 static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
 static __u32 prog_id;
+static struct perf_buffer *pb = NULL;
 
 static int do_attach(int idx, int fd, const char *name)
 {
@@ -73,7 +72,7 @@ static int do_detach(int idx, const char *name)
 
 #define SAMPLE_SIZE 64
 
-static int print_bpf_output(void *data, int size)
+static void print_bpf_output(void *ctx, int cpu, void *data, __u32 size)
 {
 	struct {
 		__u16 cookie;
@@ -83,45 +82,20 @@ static int print_bpf_output(void *data, int size)
 	int i;
 
 	if (e->cookie != 0xdead) {
-		printf("BUG cookie %x sized %d\n",
-		       e->cookie, size);
-		return LIBBPF_PERF_EVENT_ERROR;
+		printf("BUG cookie %x sized %d\n", e->cookie, size);
+		return;
 	}
 
 	printf("Pkt len: %-5d bytes. Ethernet hdr: ", e->pkt_len);
 	for (i = 0; i < 14 && i < e->pkt_len; i++)
 		printf("%02x ", e->pkt_data[i]);
 	printf("\n");
-
-	return LIBBPF_PERF_EVENT_CONT;
-}
-
-static void test_bpf_perf_event(int map_fd, int num)
-{
-	struct perf_event_attr attr = {
-		.sample_type = PERF_SAMPLE_RAW,
-		.type = PERF_TYPE_SOFTWARE,
-		.config = PERF_COUNT_SW_BPF_OUTPUT,
-		.wakeup_events = 1, /* get an fd notification for every event */
-	};
-	int i;
-
-	for (i = 0; i < num; i++) {
-		int key = i;
-
-		pmu_fds[i] = sys_perf_event_open(&attr, -1/*pid*/, i/*cpu*/,
-						 -1/*group_fd*/, 0);
-
-		assert(pmu_fds[i] >= 0);
-		assert(bpf_map_update_elem(map_fd, &key,
-					   &pmu_fds[i], BPF_ANY) == 0);
-		ioctl(pmu_fds[i], PERF_EVENT_IOC_ENABLE, 0);
-	}
 }
 
 static void sig_handler(int signo)
 {
 	do_detach(if_idx, if_name);
+	perf_buffer__free(pb);
 	exit(0);
 }
 
@@ -140,13 +114,13 @@ int main(int argc, char **argv)
 	struct bpf_prog_load_attr prog_load_attr = {
 		.prog_type	= BPF_PROG_TYPE_XDP,
 	};
+	struct perf_buffer_opts pb_opts = {};
 	const char *optstr = "F";
 	int prog_fd, map_fd, opt;
 	struct bpf_object *obj;
 	struct bpf_map *map;
 	char filename[256];
-	int ret, err, i;
-	int numcpus;
+	int ret, err;
 
 	while ((opt = getopt(argc, argv, optstr)) != -1) {
 		switch (opt) {
@@ -169,10 +143,6 @@ int main(int argc, char **argv)
 		return 1;
 	}
 
-	numcpus = get_nprocs();
-	if (numcpus > MAX_CPUS)
-		numcpus = MAX_CPUS;
-
 	snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
 	prog_load_attr.file = filename;
 
@@ -211,14 +181,17 @@ int main(int argc, char **argv)
 		return 1;
 	}
 
-	test_bpf_perf_event(map_fd, numcpus);
+	pb_opts.sample_cb = print_bpf_output;
+	pb = perf_buffer__new(map_fd, 8, &pb_opts);
+	err = libbpf_get_error(pb);
+	if (err) {
+		perror("perf_buffer setup failed");
+		return 1;
+	}
 
-	for (i = 0; i < numcpus; i++)
-		if (perf_event_mmap_header(pmu_fds[i], &headers[i]) < 0)
-			return 1;
+	while ((ret = perf_buffer__poll(pb, 1000)) >= 0) {
+	}
 
-	ret = perf_event_poller_multi(pmu_fds, headers, numcpus,
-				      print_bpf_output);
 	kill(0, SIGINT);
 	return ret;
 }
-- 
2.17.1


^ permalink raw reply related

* [PATCH v2 bpf-next 4/5] samples/bpf: switch trace_output sample to perf_buffer API
From: Andrii Nakryiko @ 2019-07-23 21:34 UTC (permalink / raw)
  To: bpf, netdev, ast, daniel, songliubraving
  Cc: andrii.nakryiko, kernel-team, Andrii Nakryiko
In-Reply-To: <20190723213445.1732339-1-andriin@fb.com>

Convert trace_output sample to libbpf's perf_buffer API.

Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Acked-by: Song Liu <songliubraving@fb.com>
---
 samples/bpf/trace_output_user.c | 43 +++++++++++----------------------
 1 file changed, 14 insertions(+), 29 deletions(-)

diff --git a/samples/bpf/trace_output_user.c b/samples/bpf/trace_output_user.c
index 2dd1d39b152a..8ee47699a870 100644
--- a/samples/bpf/trace_output_user.c
+++ b/samples/bpf/trace_output_user.c
@@ -18,9 +18,6 @@
 #include <libbpf.h>
 #include "bpf_load.h"
 #include "perf-sys.h"
-#include "trace_helpers.h"
-
-static int pmu_fd;
 
 static __u64 time_get_ns(void)
 {
@@ -31,12 +28,12 @@ static __u64 time_get_ns(void)
 }
 
 static __u64 start_time;
+static __u64 cnt;
 
 #define MAX_CNT 100000ll
 
-static int print_bpf_output(void *data, int size)
+static void print_bpf_output(void *ctx, int cpu, void *data, __u32 size)
 {
-	static __u64 cnt;
 	struct {
 		__u64 pid;
 		__u64 cookie;
@@ -45,7 +42,7 @@ static int print_bpf_output(void *data, int size)
 	if (e->cookie != 0x12345678) {
 		printf("BUG pid %llx cookie %llx sized %d\n",
 		       e->pid, e->cookie, size);
-		return LIBBPF_PERF_EVENT_ERROR;
+		return;
 	}
 
 	cnt++;
@@ -53,30 +50,14 @@ static int print_bpf_output(void *data, int size)
 	if (cnt == MAX_CNT) {
 		printf("recv %lld events per sec\n",
 		       MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
-		return LIBBPF_PERF_EVENT_DONE;
+		return;
 	}
-
-	return LIBBPF_PERF_EVENT_CONT;
-}
-
-static void test_bpf_perf_event(void)
-{
-	struct perf_event_attr attr = {
-		.sample_type = PERF_SAMPLE_RAW,
-		.type = PERF_TYPE_SOFTWARE,
-		.config = PERF_COUNT_SW_BPF_OUTPUT,
-	};
-	int key = 0;
-
-	pmu_fd = sys_perf_event_open(&attr, -1/*pid*/, 0/*cpu*/, -1/*group_fd*/, 0);
-
-	assert(pmu_fd >= 0);
-	assert(bpf_map_update_elem(map_fd[0], &key, &pmu_fd, BPF_ANY) == 0);
-	ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0);
 }
 
 int main(int argc, char **argv)
 {
+	struct perf_buffer_opts pb_opts = {};
+	struct perf_buffer *pb;
 	char filename[256];
 	FILE *f;
 	int ret;
@@ -88,16 +69,20 @@ int main(int argc, char **argv)
 		return 1;
 	}
 
-	test_bpf_perf_event();
-
-	if (perf_event_mmap(pmu_fd) < 0)
+	pb_opts.sample_cb = print_bpf_output;
+	pb = perf_buffer__new(map_fd[0], 8, &pb_opts);
+	ret = libbpf_get_error(pb);
+	if (ret) {
+		printf("failed to setup perf_buffer: %d\n", ret);
 		return 1;
+	}
 
 	f = popen("taskset 1 dd if=/dev/zero of=/dev/null", "r");
 	(void) f;
 
 	start_time = time_get_ns();
-	ret = perf_event_poller(pmu_fd, print_bpf_output);
+	while ((ret = perf_buffer__poll(pb, 1000)) >= 0 && cnt < MAX_CNT) {
+	}
 	kill(0, SIGINT);
 	return ret;
 }
-- 
2.17.1


^ permalink raw reply related

* Re: [PATCH v4 net-next 14/19] ionic: Add Tx and Rx handling
From: David Miller @ 2019-07-23 21:36 UTC (permalink / raw)
  To: snelson; +Cc: netdev
In-Reply-To: <20190722214023.9513-15-snelson@pensando.io>

From: Shannon Nelson <snelson@pensando.io>
Date: Mon, 22 Jul 2019 14:40:18 -0700

> Add both the Tx and Rx queue setup and handling.  The related
> stats display comes later.  Instead of using the generic napi
> routines used by the slow-path commands, the Tx and Rx paths
> are simplified and inlined in one file in order to get better
> compiler optimizations.
> 
> Signed-off-by: Shannon Nelson <snelson@pensando.io>

A lot of reverse christmas tree ordering violations here, please
fix all of them.

^ permalink raw reply

* Re: [PATCH V2 1/1] can: sja1000: f81601: add Fintek F81601 support
From: Saeed Mahameed @ 2019-07-23 21:38 UTC (permalink / raw)
  To: peter_hong@fintek.com.tw, wg@grandegger.com, mkl@pengutronix.de,
	hpeter@gmail.com
  Cc: hpeter+linux_kernel@gmail.com, f.suligoi@asem.it,
	linux-can@vger.kernel.org, davem@davemloft.net,
	linux-kernel@vger.kernel.org, netdev@vger.kernel.org
In-Reply-To: <1563776521-28317-1-git-send-email-hpeter+linux_kernel@gmail.com>

On Mon, 2019-07-22 at 14:22 +0800, Ji-Ze Hong (Peter Hong) wrote:
> This patch add support for Fintek PCIE to 2 CAN controller support
> 
> Signed-off-by: Ji-Ze Hong (Peter Hong) <hpeter+linux_kernel@gmail.com
> >
> ---
> Changelog:
> v2:
> 	1: Fix comment on the spinlock with write access.
> 	2: Use ARRAY_SIZE instead of F81601_PCI_MAX_CHAN.
> 	3: Check the strap pin outside the loop.
> 	4: Fix the cleanup issue in f81601_pci_add_card().
> 	5: Remove unused "channels" in struct f81601_pci_card.
> 
>  drivers/net/can/sja1000/Kconfig  |   8 ++
>  drivers/net/can/sja1000/Makefile |   1 +
>  drivers/net/can/sja1000/f81601.c | 215
> +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 224 insertions(+)
>  create mode 100644 drivers/net/can/sja1000/f81601.c
> 
> diff --git a/drivers/net/can/sja1000/Kconfig
> b/drivers/net/can/sja1000/Kconfig
> index f6dc89927ece..8588323c5138 100644
> --- a/drivers/net/can/sja1000/Kconfig
> +++ b/drivers/net/can/sja1000/Kconfig
> @@ -101,4 +101,12 @@ config CAN_TSCAN1
>  	  IRQ numbers are read from jumpers JP4 and JP5,
>  	  SJA1000 IO base addresses are chosen heuristically (first
> that works).
>  
> +config CAN_F81601
> +	tristate "Fintek F81601 PCIE to 2 CAN Controller"
> +	depends on PCI
> +	help
> +	  This driver adds support for Fintek F81601 PCIE to 2 CAN
> Controller.
> +	  It had internal 24MHz clock source, but it can be changed by
> +	  manufacturer. We can use modinfo to get usage for parameters.
> +	  Visit http://www.fintek.com.tw to get more information.
>  endif
> diff --git a/drivers/net/can/sja1000/Makefile
> b/drivers/net/can/sja1000/Makefile
> index 9253aaf9e739..6f6268543bd9 100644
> --- a/drivers/net/can/sja1000/Makefile
> +++ b/drivers/net/can/sja1000/Makefile
> @@ -13,3 +13,4 @@ obj-$(CONFIG_CAN_PEAK_PCMCIA) += peak_pcmcia.o
>  obj-$(CONFIG_CAN_PEAK_PCI) += peak_pci.o
>  obj-$(CONFIG_CAN_PLX_PCI) += plx_pci.o
>  obj-$(CONFIG_CAN_TSCAN1) += tscan1.o
> +obj-$(CONFIG_CAN_F81601) += f81601.o
> diff --git a/drivers/net/can/sja1000/f81601.c
> b/drivers/net/can/sja1000/f81601.c
> new file mode 100644
> index 000000000000..3c378de8764d
> --- /dev/null
> +++ b/drivers/net/can/sja1000/f81601.c
> @@ -0,0 +1,215 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Fintek F81601 PCIE to 2 CAN controller driver
> + *
> + * Copyright (C) 2019 Peter Hong <peter_hong@fintek.com.tw>
> + * Copyright (C) 2019 Linux Foundation
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/interrupt.h>
> +#include <linux/netdevice.h>
> +#include <linux/delay.h>
> +#include <linux/slab.h>
> +#include <linux/pci.h>
> +#include <linux/can/dev.h>
> +#include <linux/io.h>
> +#include <linux/version.h>
> +
> +#include "sja1000.h"
> +
> +#define F81601_PCI_MAX_CHAN		2
> +
> +#define F81601_DECODE_REG		0x209
> +#define F81601_IO_MODE			BIT(7)
> +#define F81601_MEM_MODE			BIT(6)
> +#define F81601_CFG_MODE			BIT(5)
> +#define F81601_CAN2_INTERNAL_CLK	BIT(3)
> +#define F81601_CAN1_INTERNAL_CLK	BIT(2)
> +#define F81601_CAN2_EN			BIT(1)
> +#define F81601_CAN1_EN			BIT(0)
> +
> +#define F81601_TRAP_REG			0x20a
> +#define F81601_CAN2_HAS_EN		BIT(4)
> +
> +struct f81601_pci_card {
> +	void __iomem *addr;
> +	spinlock_t lock;	/* use this spin lock only for write access
> */
> +	struct pci_dev *dev;
> +	struct net_device *net_dev[F81601_PCI_MAX_CHAN];
> +};
> +
> +static const struct pci_device_id f81601_pci_tbl[] = {
> +	{ PCI_DEVICE(0x1c29, 0x1703) },
> +	{},
> +};
> +
> +MODULE_DEVICE_TABLE(pci, f81601_pci_tbl);
> +
> +static bool internal_clk = 1;
> +module_param(internal_clk, bool, 0444);
> +MODULE_PARM_DESC(internal_clk, "Use internal clock, default 1
> (24MHz)");
> +
> +static unsigned int external_clk;
> +module_param(external_clk, uint, 0444);
> +MODULE_PARM_DESC(external_clk, "External Clock, must spec when
> internal_clk = 0");
> +
> +static u8 f81601_pci_read_reg(const struct sja1000_priv *priv, int
> port)
> +{
> +	return readb(priv->reg_base + port);
> +}
> +
> +static void f81601_pci_write_reg(const struct sja1000_priv *priv,
> int port,
> +				 u8 val)
> +{
> +	struct f81601_pci_card *card = priv->priv;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&card->lock, flags);
> +	writeb(val, priv->reg_base + port);
> +	readb(priv->reg_base);
> +	spin_unlock_irqrestore(&card->lock, flags);
> +}
> +
> +static void f81601_pci_del_card(struct pci_dev *pdev)
> +{
> +	struct f81601_pci_card *card = pci_get_drvdata(pdev);
> +	struct net_device *dev;
> +	int i = 0;
> +
> +	for (i = 0; i < ARRAY_SIZE(card->net_dev); i++) {
> +		dev = card->net_dev[i];
> +		if (!dev)
> +			continue;
> +
> +		dev_info(&pdev->dev, "%s: Removing %s\n", __func__,
> dev->name);
> +
> +		unregister_sja1000dev(dev);
> +		free_sja1000dev(dev);
> +	}
> +
> +	pcim_iounmap(pdev, card->addr);
> +}
> +
> +/* Probe F81601 based device for the SJA1000 chips and register each
> + * available CAN channel to SJA1000 Socket-CAN subsystem.
> + */
> +static int f81601_pci_add_card(struct pci_dev *pdev,
> +			       const struct pci_device_id *ent)
> +{
> +	struct sja1000_priv *priv;
> +	struct net_device *dev;
> +	struct f81601_pci_card *card;

nit, reverse xmas tree.

> +	int err, i, count;
> +	u8 tmp;
> +
> +	if (pcim_enable_device(pdev) < 0) {
> +		dev_err(&pdev->dev, "Failed to enable PCI device\n");
> +		return -ENODEV;
> +	}
> +
> +	dev_info(&pdev->dev, "Detected card at slot #%i\n",
> +		 PCI_SLOT(pdev->devfn));
> +
> +	card = devm_kzalloc(&pdev->dev, sizeof(*card), GFP_KERNEL);
> +	if (!card)
> +		return -ENOMEM;
> +
> +	card->dev = pdev;
> +	spin_lock_init(&card->lock);
> +
> +	pci_set_drvdata(pdev, card);
> +
> +	tmp = F81601_IO_MODE | F81601_MEM_MODE | F81601_CFG_MODE |
> +		F81601_CAN2_EN | F81601_CAN1_EN;
> +
> +	if (internal_clk) {
> +		tmp |= F81601_CAN2_INTERNAL_CLK |
> F81601_CAN1_INTERNAL_CLK;
> +
> +		dev_info(&pdev->dev,
> +			 "F81601 running with internal clock:
> 24Mhz\n");
> +	} else {
> +		dev_info(&pdev->dev,
> +			 "F81601 running with external clock: %dMhz\n",
> +			 external_clk / 1000000);
> +	}
> +
> +	pci_write_config_byte(pdev, F81601_DECODE_REG, tmp);
> +
> +	card->addr = pcim_iomap(pdev, 0, pci_resource_len(pdev, 0));
> +
> +	if (!card->addr) {
> +		err = -ENOMEM;
> +		dev_err(&pdev->dev, "%s: Failed to remap BAR\n",
> __func__);
> +		goto failure_cleanup;
> +	}
> +
> +	/* read CAN2_HW_EN strap pin to detect how many CANBUS do we
> have */
> +	count = ARRAY_SIZE(card->net_dev);
> +	pci_read_config_byte(pdev, F81601_TRAP_REG, &tmp);
> +	if (!(tmp & F81601_CAN2_HAS_EN))
> +		count = 1;
> +
> +	/* Detect available channels */
> +	for (i = 0; i < count; i++) {
> +		dev = alloc_sja1000dev(0);
> +		if (!dev) {
> +			err = -ENOMEM;
> +			goto failure_cleanup;
> +		}
> +

don't you need to rollback and cleanup/unregister previously allocated
devs ?

> +		priv = netdev_priv(dev);
> +		priv->priv = card;
> +		priv->irq_flags = IRQF_SHARED;
> +		priv->reg_base = card->addr + 0x80 * i;
> +		priv->read_reg = f81601_pci_read_reg;
> +		priv->write_reg = f81601_pci_write_reg;
> +
> +		if (internal_clk)
> +			priv->can.clock.freq = 24000000 / 2;
> +		else
> +			priv->can.clock.freq = external_clk / 2;
> +
> +		priv->ocr = OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL;
> +		priv->cdr = CDR_CBP;
> +
> +		SET_NETDEV_DEV(dev, &pdev->dev);
> +		dev->dev_id = i;
> +		dev->irq = pdev->irq;
> +
> +		/* Register SJA1000 device */
> +		err = register_sja1000dev(dev);
> +		if (err) {
> +			dev_err(&pdev->dev,
> +				"%s: Registering device failed: %x\n",
> __func__,
> +				err);
> +			free_sja1000dev(dev);
> +			goto failure_cleanup;
> +		}
> +
> +		card->net_dev[i] = dev;
> +		dev_info(&pdev->dev, "Channel #%d, %s at 0x%p, irq
> %d\n", i,
> +			 dev->name, priv->reg_base, dev->irq);
> +	}
> +
> +	return 0;
> +
> +failure_cleanup:
> +	dev_err(&pdev->dev, "%s: failed: %d. Cleaning Up.\n", __func__,
> err);
> +	f81601_pci_del_card(pdev);
> +
> +	return err;
> +}
> +
> +static struct pci_driver f81601_pci_driver = {
> +	.name =		"f81601",
> +	.id_table =	f81601_pci_tbl,
> +	.probe =	f81601_pci_add_card,
> +	.remove =	f81601_pci_del_card,
> +};
> +
> +MODULE_DESCRIPTION("Fintek F81601 PCIE to 2 CANBUS adaptor driver");
> +MODULE_AUTHOR("Peter Hong <peter_hong@fintek.com.tw>");
> +MODULE_LICENSE("GPL v2");
> +
> +module_pci_driver(f81601_pci_driver);

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox