Add LingYao
Change-Id: Iae6634ce565940904ee320c678d0f77473bebb90
This commit is contained in:
parent
7e20319bfc
commit
50c46e6857
BIN
LingYaoSNIC/.DS_Store
vendored
BIN
LingYaoSNIC/.DS_Store
vendored
Binary file not shown.
1
LingYaoSNIC/HW/README.md
Normal file
1
LingYaoSNIC/HW/README.md
Normal file
@ -0,0 +1 @@
|
||||
适配对接中移网络云华为虚拟层版本
|
32569
LingYaoSNIC/HW/config/p4_info.json
Normal file
32569
LingYaoSNIC/HW/config/p4_info.json
Normal file
File diff suppressed because it is too large
Load Diff
28
LingYaoSNIC/HW/config/smart_nic_init.cfg
Normal file
28
LingYaoSNIC/HW/config/smart_nic_init.cfg
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"vswitch_cfg": {
|
||||
"flow_merge_enable": 1,
|
||||
"bond_info": {
|
||||
"bus_name": "pci",
|
||||
"prefix": "jmnd",
|
||||
"linux-device": [],
|
||||
"dpdk-device": "b1:00.0"
|
||||
},
|
||||
"vport_info": {
|
||||
"bus_name": "vdev",
|
||||
"prefix": "jmnd_vdpa_net_"
|
||||
},
|
||||
"upcall-queue": {
|
||||
"vm-queue-total-num": 1020
|
||||
},
|
||||
"reinject-queue": {
|
||||
"vm-queue-total-num": 1020
|
||||
}
|
||||
},
|
||||
"global_cfg": {
|
||||
"nic_type": "smart_nic",
|
||||
"vnic_max_num": 255,
|
||||
"vnic_queue_num": 2040,
|
||||
"nic_driver_path": "/usr/lib64/librte_jmnd.so",
|
||||
"vdpa_status": 2
|
||||
}
|
||||
}
|
BIN
LingYaoSNIC/HW/firmware/imu_flash_snic_cqaca_1.7.6.img
Normal file
BIN
LingYaoSNIC/HW/firmware/imu_flash_snic_cqaca_1.7.6.img
Normal file
Binary file not shown.
3
LingYaoSNIC/HW/firmware/md5.txt
Normal file
3
LingYaoSNIC/HW/firmware/md5.txt
Normal file
@ -0,0 +1,3 @@
|
||||
890073cae9c0fae3edf42938e3dfd010 imu_flash_snic_cqaca.img
|
||||
3c1d9cbab63b4aae0f406c706a307681 scp_flash_cqaca_n2_2.0g_cmn_1.65g.img
|
||||
|
Binary file not shown.
@ -0,0 +1,11 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-m += vdpa.o
|
||||
|
||||
KERNELDIR ?= /lib/modules/$(shell uname -r)/build/
|
||||
# KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/jm_auxiliary.symvers
|
||||
# KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/crete.symvers
|
||||
# KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/vdpa.Module.symvers
|
||||
all:
|
||||
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
|
||||
clean:
|
||||
@\rm *.o *.ko *.mod.c modules.order .*.mod Module.symvers crete_core.mod *.mod .*.cmd .tmp_versions .crete* -rf
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,15 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-m += vhost_vdpa.o
|
||||
vhost_vdpa-y := vdpa.o
|
||||
|
||||
obj-m += vhost.o
|
||||
|
||||
KERNELDIR ?= /lib/modules/$(shell uname -r)/build/
|
||||
# KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/jm_auxiliary.symvers
|
||||
# # KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/crete.symvers
|
||||
KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/vdpa.Module.symvers
|
||||
all:
|
||||
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
|
||||
clean:
|
||||
@\rm *.o *.ko *.mod.c modules.order .*.mod Module.symvers crete_core.mod *.mod .*.cmd .tmp_versions .crete* -rf
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,325 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _VHOST_H
|
||||
#define _VHOST_H
|
||||
|
||||
#include <linux/eventfd.h>
|
||||
#include <linux/vhost.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/uio.h>
|
||||
#include <linux/virtio_config.h>
|
||||
#include <linux/virtio_ring.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/vhost_iotlb.h>
|
||||
#include <linux/irqbypass.h>
|
||||
|
||||
struct vhost_work;
|
||||
typedef void (*vhost_work_fn_t)(struct vhost_work *work);
|
||||
|
||||
#define VHOST_WORK_QUEUED 1
|
||||
struct vhost_work {
|
||||
struct llist_node node;
|
||||
vhost_work_fn_t fn;
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
/* Poll a file (eventfd or socket) */
|
||||
/* Note: there's nothing vhost specific about this structure. */
|
||||
struct vhost_poll {
|
||||
poll_table table;
|
||||
wait_queue_head_t *wqh;
|
||||
wait_queue_entry_t wait;
|
||||
struct vhost_work work;
|
||||
__poll_t mask;
|
||||
struct vhost_dev *dev;
|
||||
};
|
||||
|
||||
void vhost_work_init(struct vhost_work *work, vhost_work_fn_t fn);
|
||||
void vhost_work_queue(struct vhost_dev *dev, struct vhost_work *work);
|
||||
bool vhost_has_work(struct vhost_dev *dev);
|
||||
|
||||
void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn,
|
||||
__poll_t mask, struct vhost_dev *dev);
|
||||
int vhost_poll_start(struct vhost_poll *poll, struct file *file);
|
||||
void vhost_poll_stop(struct vhost_poll *poll);
|
||||
void vhost_poll_flush(struct vhost_poll *poll);
|
||||
void vhost_poll_queue(struct vhost_poll *poll);
|
||||
void vhost_work_flush(struct vhost_dev *dev, struct vhost_work *work);
|
||||
long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp);
|
||||
|
||||
struct vhost_log {
|
||||
u64 addr;
|
||||
u64 len;
|
||||
};
|
||||
|
||||
enum vhost_uaddr_type {
|
||||
VHOST_ADDR_DESC = 0,
|
||||
VHOST_ADDR_AVAIL = 1,
|
||||
VHOST_ADDR_USED = 2,
|
||||
VHOST_NUM_ADDRS = 3,
|
||||
};
|
||||
|
||||
struct vhost_vring_call {
|
||||
struct eventfd_ctx *ctx;
|
||||
struct irq_bypass_producer producer;
|
||||
};
|
||||
|
||||
/* The virtqueue structure describes a queue attached to a device. */
|
||||
struct vhost_virtqueue {
|
||||
struct vhost_dev *dev;
|
||||
|
||||
/* The actual ring of buffers. */
|
||||
struct mutex mutex;
|
||||
unsigned int num;
|
||||
vring_desc_t __user *desc;
|
||||
vring_avail_t __user *avail;
|
||||
vring_used_t __user *used;
|
||||
const struct vhost_iotlb_map *meta_iotlb[VHOST_NUM_ADDRS];
|
||||
struct file *kick;
|
||||
struct vhost_vring_call call_ctx;
|
||||
struct eventfd_ctx *error_ctx;
|
||||
struct eventfd_ctx *log_ctx;
|
||||
|
||||
struct vhost_poll poll;
|
||||
|
||||
/* The routine to call when the Guest pings us, or timeout. */
|
||||
vhost_work_fn_t handle_kick;
|
||||
|
||||
/* Last available index we saw. */
|
||||
u16 last_avail_idx;
|
||||
|
||||
/* Caches available index value from user. */
|
||||
u16 avail_idx;
|
||||
|
||||
/* Last index we used. */
|
||||
u16 last_used_idx;
|
||||
|
||||
/* Used flags */
|
||||
u16 used_flags;
|
||||
|
||||
/* Last used index value we have signalled on */
|
||||
u16 signalled_used;
|
||||
|
||||
/* Last used index value we have signalled on */
|
||||
bool signalled_used_valid;
|
||||
|
||||
/* Log writes to used structure. */
|
||||
bool log_used;
|
||||
u64 log_addr;
|
||||
|
||||
struct iovec iov[UIO_MAXIOV];
|
||||
struct iovec iotlb_iov[64];
|
||||
struct iovec *indirect;
|
||||
struct vring_used_elem *heads;
|
||||
/* Protected by virtqueue mutex. */
|
||||
struct vhost_iotlb *umem;
|
||||
struct vhost_iotlb *iotlb;
|
||||
void *private_data;
|
||||
u64 acked_features;
|
||||
u64 acked_backend_features;
|
||||
/* Log write descriptors */
|
||||
void __user *log_base;
|
||||
struct vhost_log *log;
|
||||
struct iovec log_iov[64];
|
||||
|
||||
/* Ring endianness. Defaults to legacy native endianness.
|
||||
* Set to true when starting a modern virtio device. */
|
||||
bool is_le;
|
||||
#ifdef CONFIG_VHOST_CROSS_ENDIAN_LEGACY
|
||||
/* Ring endianness requested by userspace for cross-endian support. */
|
||||
bool user_be;
|
||||
#endif
|
||||
u32 busyloop_timeout;
|
||||
};
|
||||
|
||||
struct vhost_msg_node {
|
||||
union {
|
||||
struct vhost_msg msg;
|
||||
struct vhost_msg_v2 msg_v2;
|
||||
};
|
||||
struct vhost_virtqueue *vq;
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
struct vhost_dev {
|
||||
struct mm_struct *mm;
|
||||
struct mutex mutex;
|
||||
struct vhost_virtqueue **vqs;
|
||||
int nvqs;
|
||||
struct eventfd_ctx *log_ctx;
|
||||
struct llist_head work_list;
|
||||
struct task_struct *worker;
|
||||
struct vhost_iotlb *umem;
|
||||
struct vhost_iotlb *iotlb;
|
||||
spinlock_t iotlb_lock;
|
||||
struct list_head read_list;
|
||||
struct list_head pending_list;
|
||||
wait_queue_head_t wait;
|
||||
int iov_limit;
|
||||
int weight;
|
||||
int byte_weight;
|
||||
u64 kcov_handle;
|
||||
bool use_worker;
|
||||
int (*msg_handler)(struct vhost_dev *dev, u32 asid,
|
||||
struct vhost_iotlb_msg *msg);
|
||||
};
|
||||
|
||||
bool vhost_exceeds_weight(struct vhost_virtqueue *vq, int pkts, int total_len);
|
||||
void vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue **vqs,
|
||||
int nvqs, int iov_limit, int weight, int byte_weight,
|
||||
bool use_worker,
|
||||
int (*msg_handler)(struct vhost_dev *dev, u32 asid,
|
||||
struct vhost_iotlb_msg *msg));
|
||||
long vhost_dev_set_owner(struct vhost_dev *dev);
|
||||
bool vhost_dev_has_owner(struct vhost_dev *dev);
|
||||
long vhost_dev_check_owner(struct vhost_dev *);
|
||||
struct vhost_iotlb *vhost_dev_reset_owner_prepare(void);
|
||||
void vhost_dev_reset_owner(struct vhost_dev *dev, struct vhost_iotlb *iotlb);
|
||||
void vhost_dev_cleanup(struct vhost_dev *);
|
||||
void vhost_dev_stop(struct vhost_dev *);
|
||||
long vhost_dev_ioctl(struct vhost_dev *, unsigned int ioctl, void __user *argp);
|
||||
long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp);
|
||||
bool vhost_vq_access_ok(struct vhost_virtqueue *vq);
|
||||
bool vhost_log_access_ok(struct vhost_dev *);
|
||||
|
||||
int vhost_get_vq_desc(struct vhost_virtqueue *,
|
||||
struct iovec iov[], unsigned int iov_count,
|
||||
unsigned int *out_num, unsigned int *in_num,
|
||||
struct vhost_log *log, unsigned int *log_num);
|
||||
void vhost_discard_vq_desc(struct vhost_virtqueue *, int n);
|
||||
|
||||
bool vhost_vq_is_setup(struct vhost_virtqueue *vq);
|
||||
int vhost_vq_init_access(struct vhost_virtqueue *);
|
||||
int vhost_add_used(struct vhost_virtqueue *, unsigned int head, int len);
|
||||
int vhost_add_used_n(struct vhost_virtqueue *, struct vring_used_elem *heads,
|
||||
unsigned count);
|
||||
void vhost_add_used_and_signal(struct vhost_dev *, struct vhost_virtqueue *,
|
||||
unsigned int id, int len);
|
||||
void vhost_add_used_and_signal_n(struct vhost_dev *, struct vhost_virtqueue *,
|
||||
struct vring_used_elem *heads, unsigned count);
|
||||
void vhost_signal(struct vhost_dev *, struct vhost_virtqueue *);
|
||||
void vhost_disable_notify(struct vhost_dev *, struct vhost_virtqueue *);
|
||||
bool vhost_vq_avail_empty(struct vhost_dev *, struct vhost_virtqueue *);
|
||||
bool vhost_enable_notify(struct vhost_dev *, struct vhost_virtqueue *);
|
||||
|
||||
int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
|
||||
unsigned int log_num, u64 len,
|
||||
struct iovec *iov, int count);
|
||||
int vq_meta_prefetch(struct vhost_virtqueue *vq);
|
||||
|
||||
struct vhost_msg_node *vhost_new_msg(struct vhost_virtqueue *vq, int type);
|
||||
void vhost_enqueue_msg(struct vhost_dev *dev,
|
||||
struct list_head *head,
|
||||
struct vhost_msg_node *node);
|
||||
struct vhost_msg_node *vhost_dequeue_msg(struct vhost_dev *dev,
|
||||
struct list_head *head);
|
||||
void vhost_set_backend_features(struct vhost_dev *dev, u64 features);
|
||||
|
||||
__poll_t vhost_chr_poll(struct file *file, struct vhost_dev *dev,
|
||||
poll_table *wait);
|
||||
ssize_t vhost_chr_read_iter(struct vhost_dev *dev, struct iov_iter *to,
|
||||
int noblock);
|
||||
ssize_t vhost_chr_write_iter(struct vhost_dev *dev,
|
||||
struct iov_iter *from);
|
||||
int vhost_init_device_iotlb(struct vhost_dev *d, bool enabled);
|
||||
|
||||
void vhost_iotlb_map_free(struct vhost_iotlb *iotlb,
|
||||
struct vhost_iotlb_map *map);
|
||||
|
||||
#define vq_err(vq, fmt, ...) do { \
|
||||
pr_debug(pr_fmt(fmt), ##__VA_ARGS__); \
|
||||
if ((vq)->error_ctx) \
|
||||
eventfd_signal((vq)->error_ctx, 1);\
|
||||
} while (0)
|
||||
|
||||
enum {
|
||||
VHOST_FEATURES = (1ULL << VIRTIO_F_NOTIFY_ON_EMPTY) |
|
||||
(1ULL << VIRTIO_RING_F_INDIRECT_DESC) |
|
||||
(1ULL << VIRTIO_RING_F_EVENT_IDX) |
|
||||
(1ULL << VHOST_F_LOG_ALL) |
|
||||
(1ULL << VIRTIO_F_ANY_LAYOUT) |
|
||||
(1ULL << VIRTIO_F_VERSION_1)
|
||||
};
|
||||
|
||||
/**
|
||||
* vhost_vq_set_backend - Set backend.
|
||||
*
|
||||
* @vq Virtqueue.
|
||||
* @private_data The private data.
|
||||
*
|
||||
* Context: Need to call with vq->mutex acquired.
|
||||
*/
|
||||
static inline void vhost_vq_set_backend(struct vhost_virtqueue *vq,
|
||||
void *private_data)
|
||||
{
|
||||
vq->private_data = private_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* vhost_vq_get_backend - Get backend.
|
||||
*
|
||||
* @vq Virtqueue.
|
||||
*
|
||||
* Context: Need to call with vq->mutex acquired.
|
||||
* Return: Private data previously set with vhost_vq_set_backend.
|
||||
*/
|
||||
static inline void *vhost_vq_get_backend(struct vhost_virtqueue *vq)
|
||||
{
|
||||
return vq->private_data;
|
||||
}
|
||||
|
||||
static inline bool vhost_has_feature(struct vhost_virtqueue *vq, int bit)
|
||||
{
|
||||
return vq->acked_features & (1ULL << bit);
|
||||
}
|
||||
|
||||
static inline bool vhost_backend_has_feature(struct vhost_virtqueue *vq, int bit)
|
||||
{
|
||||
return vq->acked_backend_features & (1ULL << bit);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VHOST_CROSS_ENDIAN_LEGACY
|
||||
static inline bool vhost_is_little_endian(struct vhost_virtqueue *vq)
|
||||
{
|
||||
return vq->is_le;
|
||||
}
|
||||
#else
|
||||
static inline bool vhost_is_little_endian(struct vhost_virtqueue *vq)
|
||||
{
|
||||
return virtio_legacy_is_little_endian() || vq->is_le;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Memory accessors */
|
||||
static inline u16 vhost16_to_cpu(struct vhost_virtqueue *vq, __virtio16 val)
|
||||
{
|
||||
return __virtio16_to_cpu(vhost_is_little_endian(vq), val);
|
||||
}
|
||||
|
||||
static inline __virtio16 cpu_to_vhost16(struct vhost_virtqueue *vq, u16 val)
|
||||
{
|
||||
return __cpu_to_virtio16(vhost_is_little_endian(vq), val);
|
||||
}
|
||||
|
||||
static inline u32 vhost32_to_cpu(struct vhost_virtqueue *vq, __virtio32 val)
|
||||
{
|
||||
return __virtio32_to_cpu(vhost_is_little_endian(vq), val);
|
||||
}
|
||||
|
||||
static inline __virtio32 cpu_to_vhost32(struct vhost_virtqueue *vq, u32 val)
|
||||
{
|
||||
return __cpu_to_virtio32(vhost_is_little_endian(vq), val);
|
||||
}
|
||||
|
||||
static inline u64 vhost64_to_cpu(struct vhost_virtqueue *vq, __virtio64 val)
|
||||
{
|
||||
return __virtio64_to_cpu(vhost_is_little_endian(vq), val);
|
||||
}
|
||||
|
||||
static inline __virtio64 cpu_to_vhost64(struct vhost_virtqueue *vq, u64 val)
|
||||
{
|
||||
return __cpu_to_virtio64(vhost_is_little_endian(vq), val);
|
||||
}
|
||||
#endif
|
@ -0,0 +1,362 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _LINUX_VDPA_H
|
||||
#define _LINUX_VDPA_H
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/vhost_iotlb.h>
|
||||
|
||||
/**
|
||||
* vDPA callback definition.
|
||||
* @callback: interrupt callback function
|
||||
* @private: the data passed to the callback function
|
||||
*/
|
||||
struct vdpa_callback {
|
||||
irqreturn_t (*callback)(void *data);
|
||||
void *private;
|
||||
};
|
||||
|
||||
/**
|
||||
* vDPA notification area
|
||||
* @addr: base address of the notification area
|
||||
* @size: size of the notification area
|
||||
*/
|
||||
struct vdpa_notification_area {
|
||||
resource_size_t addr;
|
||||
resource_size_t size;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct vdpa_vq_state_split - vDPA split virtqueue state
|
||||
* @avail_index: available index
|
||||
*/
|
||||
struct vdpa_vq_state_split {
|
||||
u16 avail_index;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct vdpa_vq_state_packed - vDPA packed virtqueue state
|
||||
* @last_avail_counter: last driver ring wrap counter observed by device
|
||||
* @last_avail_idx: device available index
|
||||
* @last_used_counter: device ring wrap counter
|
||||
* @last_used_idx: used index
|
||||
*/
|
||||
struct vdpa_vq_state_packed {
|
||||
u16 last_avail_counter:1;
|
||||
u16 last_avail_idx:15;
|
||||
u16 last_used_counter:1;
|
||||
u16 last_used_idx:15;
|
||||
};
|
||||
|
||||
struct vdpa_vq_state {
|
||||
union {
|
||||
struct vdpa_vq_state_split split;
|
||||
struct vdpa_vq_state_packed packed;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* vDPA device - representation of a vDPA device
|
||||
* @dev: underlying device
|
||||
* @dma_dev: the actual device that is performing DMA
|
||||
* @config: the configuration ops for this device.
|
||||
* @index: device index
|
||||
* @features_valid: were features initialized? for legacy guests
|
||||
*/
|
||||
struct vdpa_device {
|
||||
struct device dev;
|
||||
struct device *dma_dev;
|
||||
const struct vdpa_config_ops *config;
|
||||
unsigned int index;
|
||||
bool features_valid;
|
||||
int nvqs;
|
||||
};
|
||||
|
||||
/**
|
||||
* vDPA IOVA range - the IOVA range support by the device
|
||||
* @first: start of the IOVA range
|
||||
* @last: end of the IOVA range
|
||||
*/
|
||||
struct vdpa_iova_range {
|
||||
u64 first;
|
||||
u64 last;
|
||||
};
|
||||
|
||||
/**
|
||||
* vDPA_config_ops - operations for configuring a vDPA device.
|
||||
* Note: vDPA device drivers are required to implement all of the
|
||||
* operations unless it is mentioned to be optional in the following
|
||||
* list.
|
||||
*
|
||||
* @set_vq_address: Set the address of virtqueue
|
||||
* @vdev: vdpa device
|
||||
* @idx: virtqueue index
|
||||
* @desc_area: address of desc area
|
||||
* @driver_area: address of driver area
|
||||
* @device_area: address of device area
|
||||
* Returns integer: success (0) or error (< 0)
|
||||
* @set_vq_num: Set the size of virtqueue
|
||||
* @vdev: vdpa device
|
||||
* @idx: virtqueue index
|
||||
* @num: the size of virtqueue
|
||||
* @kick_vq: Kick the virtqueue
|
||||
* @vdev: vdpa device
|
||||
* @idx: virtqueue index
|
||||
* @set_vq_cb: Set the interrupt callback function for
|
||||
* a virtqueue
|
||||
* @vdev: vdpa device
|
||||
* @idx: virtqueue index
|
||||
* @cb: virtio-vdev interrupt callback structure
|
||||
* @set_vq_ready: Set ready status for a virtqueue
|
||||
* @vdev: vdpa device
|
||||
* @idx: virtqueue index
|
||||
* @ready: ready (true) not ready(false)
|
||||
* @get_vq_ready: Get ready status for a virtqueue
|
||||
* @vdev: vdpa device
|
||||
* @idx: virtqueue index
|
||||
* Returns boolean: ready (true) or not (false)
|
||||
* @set_vq_state: Set the state for a virtqueue
|
||||
* @vdev: vdpa device
|
||||
* @idx: virtqueue index
|
||||
* @state: pointer to set virtqueue state (last_avail_idx)
|
||||
* Returns integer: success (0) or error (< 0)
|
||||
* @get_vq_state: Get the state for a virtqueue
|
||||
* @vdev: vdpa device
|
||||
* @idx: virtqueue index
|
||||
* @state: pointer to returned state (last_avail_idx)
|
||||
* @get_vq_notification: Get the notification area for a virtqueue
|
||||
* @vdev: vdpa device
|
||||
* @idx: virtqueue index
|
||||
* Returns the notifcation area
|
||||
* @get_vq_irq: Get the irq number of a virtqueue (optional,
|
||||
* but must implemented if require vq irq offloading)
|
||||
* @vdev: vdpa device
|
||||
* @idx: virtqueue index
|
||||
* Returns int: irq number of a virtqueue,
|
||||
* negative number if no irq assigned.
|
||||
* @get_vq_align: Get the virtqueue align requirement
|
||||
* for the device
|
||||
* @vdev: vdpa device
|
||||
* Returns virtqueue algin requirement
|
||||
* @get_features: Get virtio features supported by the device
|
||||
* @vdev: vdpa device
|
||||
* Returns the virtio features support by the
|
||||
* device
|
||||
* @set_features: Set virtio features supported by the driver
|
||||
* @vdev: vdpa device
|
||||
* @features: feature support by the driver
|
||||
* Returns integer: success (0) or error (< 0)
|
||||
* @set_config_cb: Set the config interrupt callback
|
||||
* @vdev: vdpa device
|
||||
* @cb: virtio-vdev interrupt callback structure
|
||||
* @get_vq_num_max: Get the max size of virtqueue
|
||||
* @vdev: vdpa device
|
||||
* Returns u16: max size of virtqueue
|
||||
* @get_device_id: Get virtio device id
|
||||
* @vdev: vdpa device
|
||||
* Returns u32: virtio device id
|
||||
* @get_vendor_id: Get id for the vendor that provides this device
|
||||
* @vdev: vdpa device
|
||||
* Returns u32: virtio vendor id
|
||||
* @get_status: Get the device status
|
||||
* @vdev: vdpa device
|
||||
* Returns u8: virtio device status
|
||||
* @set_status: Set the device status
|
||||
* @vdev: vdpa device
|
||||
* @status: virtio device status
|
||||
* @get_config: Read from device specific configuration space
|
||||
* @vdev: vdpa device
|
||||
* @offset: offset from the beginning of
|
||||
* configuration space
|
||||
* @buf: buffer used to read to
|
||||
* @len: the length to read from
|
||||
* configuration space
|
||||
* @set_config: Write to device specific configuration space
|
||||
* @vdev: vdpa device
|
||||
* @offset: offset from the beginning of
|
||||
* configuration space
|
||||
* @buf: buffer used to write from
|
||||
* @len: the length to write to
|
||||
* configuration space
|
||||
* @get_generation: Get device config generation (optional)
|
||||
* @vdev: vdpa device
|
||||
* Returns u32: device generation
|
||||
* @get_iova_range: Get supported iova range (optional)
|
||||
* @vdev: vdpa device
|
||||
* Returns the iova range supported by
|
||||
* the device.
|
||||
* @set_map: Set device memory mapping (optional)
|
||||
* Needed for device that using device
|
||||
* specific DMA translation (on-chip IOMMU)
|
||||
* @vdev: vdpa device
|
||||
* @iotlb: vhost memory mapping to be
|
||||
* used by the vDPA
|
||||
* Returns integer: success (0) or error (< 0)
|
||||
* @dma_map: Map an area of PA to IOVA (optional)
|
||||
* Needed for device that using device
|
||||
* specific DMA translation (on-chip IOMMU)
|
||||
* and preferring incremental map.
|
||||
* @vdev: vdpa device
|
||||
* @iova: iova to be mapped
|
||||
* @size: size of the area
|
||||
* @pa: physical address for the map
|
||||
* @perm: device access permission (VHOST_MAP_XX)
|
||||
* Returns integer: success (0) or error (< 0)
|
||||
* @dma_unmap: Unmap an area of IOVA (optional but
|
||||
* must be implemented with dma_map)
|
||||
* Needed for device that using device
|
||||
* specific DMA translation (on-chip IOMMU)
|
||||
* and preferring incremental unmap.
|
||||
* @vdev: vdpa device
|
||||
* @iova: iova to be unmapped
|
||||
* @size: size of the area
|
||||
* Returns integer: success (0) or error (< 0)
|
||||
* @free: Free resources that belongs to vDPA (optional)
|
||||
* @vdev: vdpa device
|
||||
*/
|
||||
struct vdpa_config_ops {
|
||||
/* Virtqueue ops */
|
||||
int (*set_vq_address)(struct vdpa_device *vdev,
|
||||
u16 idx, u64 desc_area, u64 driver_area,
|
||||
u64 device_area);
|
||||
void (*set_vq_num)(struct vdpa_device *vdev, u16 idx, u32 num);
|
||||
void (*kick_vq)(struct vdpa_device *vdev, u16 idx);
|
||||
void (*set_vq_cb)(struct vdpa_device *vdev, u16 idx,
|
||||
struct vdpa_callback *cb);
|
||||
void (*set_vq_ready)(struct vdpa_device *vdev, u16 idx, bool ready);
|
||||
bool (*get_vq_ready)(struct vdpa_device *vdev, u16 idx);
|
||||
int (*set_vq_state)(struct vdpa_device *vdev, u16 idx,
|
||||
const struct vdpa_vq_state *state);
|
||||
int (*get_vq_state)(struct vdpa_device *vdev, u16 idx,
|
||||
struct vdpa_vq_state *state);
|
||||
struct vdpa_notification_area
|
||||
(*get_vq_notification)(struct vdpa_device *vdev, u16 idx);
|
||||
/* vq irq is not expected to be changed once DRIVER_OK is set */
|
||||
int (*get_vq_irq)(struct vdpa_device *vdv, u16 idx);
|
||||
|
||||
/* Device ops */
|
||||
u32 (*get_vq_align)(struct vdpa_device *vdev);
|
||||
u64 (*get_features)(struct vdpa_device *vdev);
|
||||
int (*set_features)(struct vdpa_device *vdev, u64 features);
|
||||
void (*set_config_cb)(struct vdpa_device *vdev,
|
||||
struct vdpa_callback *cb);
|
||||
u16 (*get_vq_num_max)(struct vdpa_device *vdev);
|
||||
u32 (*get_device_id)(struct vdpa_device *vdev);
|
||||
u32 (*get_vendor_id)(struct vdpa_device *vdev);
|
||||
u8 (*get_status)(struct vdpa_device *vdev);
|
||||
void (*set_status)(struct vdpa_device *vdev, u8 status);
|
||||
void (*get_config)(struct vdpa_device *vdev, unsigned int offset,
|
||||
void *buf, unsigned int len);
|
||||
void (*set_config)(struct vdpa_device *vdev, unsigned int offset,
|
||||
const void *buf, unsigned int len);
|
||||
u32 (*get_generation)(struct vdpa_device *vdev);
|
||||
struct vdpa_iova_range (*get_iova_range)(struct vdpa_device *vdev);
|
||||
|
||||
/* Migration ops */
|
||||
int (*set_log_base)(struct vdpa_device *vdev, u64 log_base, u64 log_size);
|
||||
|
||||
/* DMA ops */
|
||||
int (*set_map)(struct vdpa_device *vdev, struct vhost_iotlb *iotlb);
|
||||
int (*dma_map)(struct vdpa_device *vdev, u64 iova, u64 size,
|
||||
u64 pa, u32 perm);
|
||||
int (*dma_unmap)(struct vdpa_device *vdev, u64 iova, u64 size);
|
||||
|
||||
/* Free device resources */
|
||||
void (*free)(struct vdpa_device *vdev);
|
||||
};
|
||||
|
||||
struct vdpa_device *__vdpa_alloc_device(struct device *parent,
|
||||
const struct vdpa_config_ops *config,
|
||||
int nvqs,
|
||||
size_t size);
|
||||
|
||||
#define vdpa_alloc_device(dev_struct, member, parent, config, nvqs) \
|
||||
container_of(__vdpa_alloc_device( \
|
||||
parent, config, nvqs, \
|
||||
sizeof(dev_struct) + \
|
||||
BUILD_BUG_ON_ZERO(offsetof( \
|
||||
dev_struct, member))), \
|
||||
dev_struct, member)
|
||||
|
||||
int vdpa_register_device(struct vdpa_device *vdev);
|
||||
void vdpa_unregister_device(struct vdpa_device *vdev);
|
||||
|
||||
/**
|
||||
* vdpa_driver - operations for a vDPA driver
|
||||
* @driver: underlying device driver
|
||||
* @probe: the function to call when a device is found. Returns 0 or -errno.
|
||||
* @remove: the function to call when a device is removed.
|
||||
*/
|
||||
struct vdpa_driver {
|
||||
struct device_driver driver;
|
||||
int (*probe)(struct vdpa_device *vdev);
|
||||
void (*remove)(struct vdpa_device *vdev);
|
||||
};
|
||||
|
||||
#define vdpa_register_driver(drv) \
|
||||
__vdpa_register_driver(drv, THIS_MODULE)
|
||||
int __vdpa_register_driver(struct vdpa_driver *drv, struct module *owner);
|
||||
void vdpa_unregister_driver(struct vdpa_driver *drv);
|
||||
|
||||
#define module_vdpa_driver(__vdpa_driver) \
|
||||
module_driver(__vdpa_driver, vdpa_register_driver, \
|
||||
vdpa_unregister_driver)
|
||||
|
||||
static inline struct vdpa_driver *drv_to_vdpa(struct device_driver *driver)
|
||||
{
|
||||
return container_of(driver, struct vdpa_driver, driver);
|
||||
}
|
||||
|
||||
static inline struct vdpa_device *dev_to_vdpa(struct device *_dev)
|
||||
{
|
||||
return container_of(_dev, struct vdpa_device, dev);
|
||||
}
|
||||
|
||||
static inline void *vdpa_get_drvdata(const struct vdpa_device *vdev)
|
||||
{
|
||||
return dev_get_drvdata(&vdev->dev);
|
||||
}
|
||||
|
||||
static inline void vdpa_set_drvdata(struct vdpa_device *vdev, void *data)
|
||||
{
|
||||
dev_set_drvdata(&vdev->dev, data);
|
||||
}
|
||||
|
||||
static inline struct device *vdpa_get_dma_dev(struct vdpa_device *vdev)
|
||||
{
|
||||
return vdev->dma_dev;
|
||||
}
|
||||
|
||||
static inline void vdpa_reset(struct vdpa_device *vdev)
|
||||
{
|
||||
const struct vdpa_config_ops *ops = vdev->config;
|
||||
|
||||
vdev->features_valid = false;
|
||||
ops->set_status(vdev, 0);
|
||||
}
|
||||
|
||||
static inline int vdpa_set_features(struct vdpa_device *vdev, u64 features)
|
||||
{
|
||||
const struct vdpa_config_ops *ops = vdev->config;
|
||||
|
||||
vdev->features_valid = true;
|
||||
return ops->set_features(vdev, features);
|
||||
}
|
||||
|
||||
|
||||
static inline void vdpa_get_config(struct vdpa_device *vdev, unsigned offset,
|
||||
void *buf, unsigned int len)
|
||||
{
|
||||
const struct vdpa_config_ops *ops = vdev->config;
|
||||
|
||||
/*
|
||||
* Config accesses aren't supposed to trigger before features are set.
|
||||
* If it does happen we assume a legacy guest.
|
||||
*/
|
||||
if (!vdev->features_valid)
|
||||
vdpa_set_features(vdev, 0);
|
||||
ops->get_config(vdev, offset, buf, len);
|
||||
}
|
||||
|
||||
#endif /* _LINUX_VDPA_H */
|
@ -0,0 +1,15 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-m += vdpa.o
|
||||
|
||||
KERNELDIR ?= /lib/modules/$(shell uname -r)/build/
|
||||
# KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/jm_auxiliary.symvers
|
||||
# KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/crete.symvers
|
||||
# KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/vdpa.Module.symvers
|
||||
all:
|
||||
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
|
||||
|
||||
install:
|
||||
install -D -m 644 Module.symvers /lib/modules/$(shell uname -r)/extern-symvers/vdpa.symvers
|
||||
|
||||
clean:
|
||||
@\rm *.o *.ko *.mod.c modules.order .*.mod Module.symvers crete_core.mod *.mod .*.cmd .tmp_versions .crete* -rf
|
@ -0,0 +1,184 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* vDPA bus.
|
||||
*
|
||||
* Copyright (c) 2020, Red Hat. All rights reserved.
|
||||
* Author: Jason Wang <jasowang@redhat.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vdpa.h>
|
||||
|
||||
static DEFINE_IDA(vdpa_index_ida);
|
||||
|
||||
static int vdpa_dev_probe(struct device *d)
|
||||
{
|
||||
struct vdpa_device *vdev = dev_to_vdpa(d);
|
||||
struct vdpa_driver *drv = drv_to_vdpa(vdev->dev.driver);
|
||||
int ret = 0;
|
||||
|
||||
if (drv && drv->probe)
|
||||
ret = drv->probe(vdev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int vdpa_dev_remove(struct device *d)
|
||||
{
|
||||
struct vdpa_device *vdev = dev_to_vdpa(d);
|
||||
struct vdpa_driver *drv = drv_to_vdpa(vdev->dev.driver);
|
||||
|
||||
if (drv && drv->remove)
|
||||
drv->remove(vdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct bus_type vdpa_bus = {
|
||||
.name = "vdpa",
|
||||
.probe = vdpa_dev_probe,
|
||||
.remove = vdpa_dev_remove,
|
||||
};
|
||||
|
||||
static void vdpa_release_dev(struct device *d)
|
||||
{
|
||||
struct vdpa_device *vdev = dev_to_vdpa(d);
|
||||
const struct vdpa_config_ops *ops = vdev->config;
|
||||
|
||||
if (ops->free)
|
||||
ops->free(vdev);
|
||||
|
||||
ida_simple_remove(&vdpa_index_ida, vdev->index);
|
||||
kfree(vdev);
|
||||
}
|
||||
|
||||
/**
|
||||
* __vdpa_alloc_device - allocate and initilaize a vDPA device
|
||||
* This allows driver to some prepartion after device is
|
||||
* initialized but before registered.
|
||||
* @parent: the parent device
|
||||
* @config: the bus operations that is supported by this device
|
||||
* @nvqs: number of virtqueues supported by this device
|
||||
* @size: size of the parent structure that contains private data
|
||||
*
|
||||
* Driver should use vdpa_alloc_device() wrapper macro instead of
|
||||
* using this directly.
|
||||
*
|
||||
* Returns an error when parent/config/dma_dev is not set or fail to get
|
||||
* ida.
|
||||
*/
|
||||
struct vdpa_device *__vdpa_alloc_device(struct device *parent,
|
||||
const struct vdpa_config_ops *config,
|
||||
int nvqs,
|
||||
size_t size)
|
||||
{
|
||||
struct vdpa_device *vdev;
|
||||
int err = -EINVAL;
|
||||
|
||||
if (!config)
|
||||
goto err;
|
||||
|
||||
if (!!config->dma_map != !!config->dma_unmap)
|
||||
goto err;
|
||||
|
||||
err = -ENOMEM;
|
||||
vdev = kzalloc(size, GFP_KERNEL);
|
||||
if (!vdev)
|
||||
goto err;
|
||||
|
||||
err = ida_simple_get(&vdpa_index_ida, 0, 0, GFP_KERNEL);
|
||||
if (err < 0)
|
||||
goto err_ida;
|
||||
|
||||
vdev->dev.bus = &vdpa_bus;
|
||||
vdev->dev.parent = parent;
|
||||
vdev->dev.release = vdpa_release_dev;
|
||||
vdev->index = err;
|
||||
vdev->config = config;
|
||||
vdev->features_valid = false;
|
||||
vdev->nvqs = nvqs;
|
||||
|
||||
err = dev_set_name(&vdev->dev, "vdpa%u", vdev->index);
|
||||
if (err)
|
||||
goto err_name;
|
||||
|
||||
device_initialize(&vdev->dev);
|
||||
|
||||
return vdev;
|
||||
|
||||
err_name:
|
||||
ida_simple_remove(&vdpa_index_ida, vdev->index);
|
||||
err_ida:
|
||||
kfree(vdev);
|
||||
err:
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__vdpa_alloc_device);
|
||||
|
||||
/**
|
||||
* vdpa_register_device - register a vDPA device
|
||||
* Callers must have a succeed call of vdpa_alloc_device() before.
|
||||
* @vdev: the vdpa device to be registered to vDPA bus
|
||||
*
|
||||
* Returns an error when fail to add to vDPA bus
|
||||
*/
|
||||
int vdpa_register_device(struct vdpa_device *vdev)
|
||||
{
|
||||
return device_add(&vdev->dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vdpa_register_device);
|
||||
|
||||
/**
|
||||
* vdpa_unregister_device - unregister a vDPA device
|
||||
* @vdev: the vdpa device to be unregisted from vDPA bus
|
||||
*/
|
||||
void vdpa_unregister_device(struct vdpa_device *vdev)
|
||||
{
|
||||
device_unregister(&vdev->dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vdpa_unregister_device);
|
||||
|
||||
/**
|
||||
* __vdpa_register_driver - register a vDPA device driver
|
||||
* @drv: the vdpa device driver to be registered
|
||||
* @owner: module owner of the driver
|
||||
*
|
||||
* Returns an err when fail to do the registration
|
||||
*/
|
||||
int __vdpa_register_driver(struct vdpa_driver *drv, struct module *owner)
|
||||
{
|
||||
drv->driver.bus = &vdpa_bus;
|
||||
drv->driver.owner = owner;
|
||||
|
||||
return driver_register(&drv->driver);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__vdpa_register_driver);
|
||||
|
||||
/**
|
||||
* vdpa_unregister_driver - unregister a vDPA device driver
|
||||
* @drv: the vdpa device driver to be unregistered
|
||||
*/
|
||||
void vdpa_unregister_driver(struct vdpa_driver *drv)
|
||||
{
|
||||
driver_unregister(&drv->driver);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vdpa_unregister_driver);
|
||||
|
||||
static int vdpa_init(void)
|
||||
{
|
||||
return bus_register(&vdpa_bus);
|
||||
}
|
||||
|
||||
static void __exit vdpa_exit(void)
|
||||
{
|
||||
bus_unregister(&vdpa_bus);
|
||||
ida_destroy(&vdpa_index_ida);
|
||||
}
|
||||
core_initcall(vdpa_init);
|
||||
module_exit(vdpa_exit);
|
||||
|
||||
MODULE_AUTHOR("Jason Wang <jasowang@redhat.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -0,0 +1,15 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-m += vhost_vdpa.o
|
||||
vhost_vdpa-y := vdpa.o
|
||||
|
||||
obj-m += vhost.o
|
||||
|
||||
KERNELDIR ?= /lib/modules/$(shell uname -r)/build/
|
||||
# KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/jm_auxiliary.symvers
|
||||
# # KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/crete.symvers
|
||||
KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/vdpa.Module.symvers
|
||||
all:
|
||||
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
|
||||
clean:
|
||||
@\rm *.o *.ko *.mod.c modules.order .*.mod Module.symvers crete_core.mod *.mod .*.cmd .tmp_versions .crete* -rf
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
12
LingYaoSNIC/HW/kernel/kernel-crete-front-driver/README
Normal file
12
LingYaoSNIC/HW/kernel/kernel-crete-front-driver/README
Normal file
@ -0,0 +1,12 @@
|
||||
kernel-crete-front-driver 目录:
|
||||
说明:
|
||||
云豹内核pf驱动+vdpa驱动
|
||||
编译方式:
|
||||
sh build_nic.sh anolis_kernel龙蜥系统编译
|
||||
sh build_nic.sh openeuler_kernel 欧拉系统编译
|
||||
sh build_nic.sh all 编译所有驱动
|
||||
编译产出物:
|
||||
crete_core.ko 基础通道驱动
|
||||
crete_pnic.ko pf驱动
|
||||
jm_auxiliary.ko auxiliary驱动
|
||||
crete_vdpa.ko vdpa驱动
|
19
LingYaoSNIC/HW/kernel/kernel-crete-front-driver/build.sh
Normal file
19
LingYaoSNIC/HW/kernel/kernel-crete-front-driver/build.sh
Normal file
@ -0,0 +1,19 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
# Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
#!/usr/bin/env bash
|
||||
function build_core() {
|
||||
pushd crete-core
|
||||
make clean
|
||||
make
|
||||
make install
|
||||
popd
|
||||
}
|
||||
function build_vnet() {
|
||||
pushd crete-vnet
|
||||
make clean
|
||||
make
|
||||
popd
|
||||
}
|
||||
|
||||
build_core
|
||||
build_vnet
|
136
LingYaoSNIC/HW/kernel/kernel-crete-front-driver/build_nic.sh
Executable file
136
LingYaoSNIC/HW/kernel/kernel-crete-front-driver/build_nic.sh
Executable file
@ -0,0 +1,136 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#!/bin/bash
|
||||
# common build rules useful for out-of-tree Linux driver builds
|
||||
#
|
||||
distro_info_dict=(/etc/anolis-release \
|
||||
/etc/bclinux-release \
|
||||
/etc/openEuler-release)
|
||||
OS_KEY=""
|
||||
distro_version=""
|
||||
exit_not_found_failure() { exit 3; }
|
||||
|
||||
find_distro_info()
|
||||
{
|
||||
# Save the first valid kernel source path
|
||||
for file in "${distro_info_dict[@]}"; do
|
||||
if [ -f ${file} ]; then
|
||||
distro_version=${file}
|
||||
break
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
get_os_key()
|
||||
{
|
||||
if [ -z "${distro_version}" ]; then
|
||||
CFLAGS_KEY=""
|
||||
return
|
||||
fi
|
||||
distro_info=`cat ${distro_version}`
|
||||
if [ -z "${distro_info}" ]; then
|
||||
echo "cat ${distro_info} is null"
|
||||
fi
|
||||
case $distro_info in
|
||||
"Anolis OS release 8.8")
|
||||
echo "You system is Anolis OS release 8.8"
|
||||
OS_KEY="anolis-8.8"
|
||||
CFLAGS_KEY="-DSNIC_ANOLIS_VERSION14"
|
||||
;;
|
||||
"Anolis OS release 8.6")
|
||||
echo "You system is Anolis OS release 8.6"
|
||||
OS_KEY="anolis-8.6"
|
||||
CFLAGS_KEY="-DSNIC_ANOLIS_VERSION14"
|
||||
;;
|
||||
"BigCloud Enterprise Linux release 21.10U4 LTS")
|
||||
echo "You system is BigCloud Enterprise Linux release 21.10U4 LTS"
|
||||
OS_KEY="bclinux-21.10U4"
|
||||
CFLAGS_KEY="-DBCLINUX2110U4"
|
||||
;;
|
||||
*)
|
||||
echo "You system is $distro_info"
|
||||
CFLAGS_KEY=""
|
||||
OS_KEY="default"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 [all | anolis_kernel | openeuler_kernel | clean]"
|
||||
echo "all : build all kernels"
|
||||
echo "anolis_kernel : build snic with anolis 5.10.134-14"
|
||||
echo "openeuler_kernel : build snic with openeuler 5.10.0-136.12"
|
||||
echo "clean : clean the anolis the kernel"
|
||||
exit 1
|
||||
}
|
||||
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
find_distro_info
|
||||
get_os_key
|
||||
|
||||
case "$1" in
|
||||
anolis_kernel)
|
||||
echo "Build nic modules"
|
||||
echo "build crete core modules"
|
||||
cd crete-core
|
||||
make EXTRA_CFLAGS="-DSNIC_ANOLIS_VERSION14"
|
||||
make install
|
||||
cd ..
|
||||
echo "build crete pnic modules"
|
||||
cd crete-pnic
|
||||
make EXTRA_CFLAGS="-DSNIC_ANOLIS_VERSION14"
|
||||
;;
|
||||
openeuler_kernel)
|
||||
echo "Build nic modules"
|
||||
echo "build crete core modules"
|
||||
cd crete-core
|
||||
make clean
|
||||
make EXTRA_CFLAGS="-DSNIC_OPENEULER_VERSION136"
|
||||
make install
|
||||
cd ..
|
||||
echo "build crete pnic modules"
|
||||
cd crete-pnic
|
||||
make clean
|
||||
make EXTRA_CFLAGS="-DSNIC_OPENEULER_VERSION136"
|
||||
cd ../
|
||||
echo "build crete vdpa modules"
|
||||
cd crete-vnet
|
||||
./build_euler.sh
|
||||
;;
|
||||
all)
|
||||
echo "Build nic modules"
|
||||
echo "build crete core modules"
|
||||
echo "EXTRA_CFLAGS is $CFLAGS_KEY"
|
||||
cd crete-core
|
||||
make clean
|
||||
make EXTRA_CFLAGS=$CFLAGS_KEY
|
||||
cd ..
|
||||
echo "build crete pnic modules"
|
||||
cd crete-pnic
|
||||
make clean
|
||||
make EXTRA_CFLAGS=$CFLAGS_KEY
|
||||
;;
|
||||
clean)
|
||||
echo "Clean build dir ......"
|
||||
cd crete-core
|
||||
make clean
|
||||
cd ..
|
||||
cd crete-pnic
|
||||
make clean
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "Building kernel..."
|
||||
|
||||
echo "Building kernel..."
|
||||
|
@ -0,0 +1,58 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# EXTRA_CFLAGS += -DCONFIG_NOSIM_DEBUG
|
||||
KBUILD :=/lib/modules/$(shell uname -r)/build
|
||||
ifeq ($(KERNELRELEASE), )
|
||||
DRIVER := crete_core
|
||||
COMMON_MK ?= $(wildcard common.mk)
|
||||
ifeq (${COMMON_MK},)
|
||||
$(error Cannot find common.mk build rules)
|
||||
else
|
||||
include ${COMMON_MK}
|
||||
endif
|
||||
|
||||
all:
|
||||
+$(call kernelbuild,modules)
|
||||
clean:
|
||||
+$(call kernelbuild,clean)
|
||||
@\rm *.o *.ko *.mod.c modules.order .*.mod Module.symvers crete_core.mod .*.cmd .tmp_versions -rf
|
||||
install:
|
||||
install -D -m 644 Module.symvers /lib/modules/$(shell uname -r)/extern-symvers/crete.symvers
|
||||
|
||||
auxiliary_info:
|
||||
@./scripts/check_aux_bus.sh --verbose --ksrc="${KSRC}" --build-kernel="${BUILD_KERNEL}"
|
||||
|
||||
ifeq (${NEED_AUX_BUS},1)
|
||||
all: auxiliary_info
|
||||
endif
|
||||
|
||||
else
|
||||
ifeq (${NEED_AUX_BUS},2)
|
||||
KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/jm_auxiliary.symvers
|
||||
export KBUILD_EXTRA_SYMBOLS
|
||||
endif
|
||||
obj-m := crete_core.o
|
||||
crete_core-y := crete.o \
|
||||
crete_rdma_dev.o \
|
||||
crete_rdma_adapt.o \
|
||||
crete_aux_dev.o \
|
||||
crete_cmd.o \
|
||||
crete_cmd_if.o \
|
||||
crete_txrx.o \
|
||||
crete_event.o \
|
||||
crete_sriov.o \
|
||||
crete_eswitch.o \
|
||||
crete_devlink.o \
|
||||
crete_dcb_nl.o \
|
||||
crete_sriov_sysfs.o \
|
||||
crete_ptp.o \
|
||||
crete_stub.o \
|
||||
crete_ethtool.o \
|
||||
crete_eswoffloads.o \
|
||||
crete_fw_update.o \
|
||||
crete_pldmfw_lib.o \
|
||||
crete_rep.o \
|
||||
crete_core_debugfs.o \
|
||||
crete_lag.o \
|
||||
crete_lag_debugfs.o \
|
||||
crete_debugfs_statistics.o
|
||||
endif
|
@ -0,0 +1,28 @@
|
||||
编译提示:
|
||||
SIM环境编译时:需关闭CONFIG_NOSIM_DEBUG
|
||||
内核模拟环境调试:需打开CONFIG_NOSIM_DEBUG
|
||||
默认关闭:CONFIG_NOSIM_DEBUG
|
||||
|
||||
|
||||
定义后端编号为idx的tx q的控制寄存器
|
||||
0x1000 + (idx * 0x100) 最多8个
|
||||
|
||||
定义后端编号为idx的tx q的描述符长度寄存器
|
||||
0x1004 + (idx * 0x100)
|
||||
|
||||
定义描述符地址lo寄存器
|
||||
0x1008 + idx * 0x100
|
||||
|
||||
定义描述符地址hi寄存器
|
||||
0x100c + idx * 0x100
|
||||
|
||||
定义doorbell寄存器
|
||||
0x1010 + idx * 0x100
|
||||
|
||||
定义中断使能寄存器 0x3000 + (idx * 0x10)
|
||||
|
||||
增加netlink套接字,用于后续用户态调试
|
||||
测试用例详见ssh://git@bit.jaguarmicro.com:7999/~foryun.ma/shell_kernel_test.git 中,test_netlink函数
|
||||
|
||||
|
||||
|
@ -0,0 +1,433 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
# Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
|
||||
#
|
||||
# common Makefile rules useful for out-of-tree Linux driver builds
|
||||
#
|
||||
# Usage: include filename.mk
|
||||
#
|
||||
# After including, you probably want to add a minimum_kver_check call
|
||||
#
|
||||
# Required Variables:
|
||||
# DRIVER
|
||||
# -- Set to the lowercase driver name
|
||||
|
||||
#####################
|
||||
# Helpful functions #
|
||||
#####################
|
||||
|
||||
readlink = $(shell readlink -f ${1})
|
||||
|
||||
# helper functions for converting kernel version to version codes
|
||||
get_kver = $(or $(word ${2},$(subst ., ,${1})),0)
|
||||
get_kvercode = $(shell [ "${1}" -ge 0 -a "${1}" -le 255 2>/dev/null ] && \
|
||||
[ "${2}" -ge 0 -a "${2}" -le 255 2>/dev/null ] && \
|
||||
[ "${3}" -ge 0 -a "${3}" -le 255 2>/dev/null ] && \
|
||||
printf %d $$(( ( ${1} << 16 ) + ( ${2} << 8 ) + ( ${3} ) )) )
|
||||
|
||||
################
|
||||
# depmod Macro #
|
||||
################
|
||||
|
||||
cmd_depmod = /sbin/depmod $(if ${SYSTEM_MAP_FILE},-e -F ${SYSTEM_MAP_FILE}) \
|
||||
$(if $(strip ${INSTALL_MOD_PATH}),-b ${INSTALL_MOD_PATH}) \
|
||||
-a ${KVER}
|
||||
|
||||
################
|
||||
# dracut Macro #
|
||||
################
|
||||
|
||||
cmd_initrd := $(shell \
|
||||
if which dracut > /dev/null 2>&1 ; then \
|
||||
echo "dracut --force"; \
|
||||
elif which update-initramfs > /dev/null 2>&1 ; then \
|
||||
echo "update-initramfs -u"; \
|
||||
fi )
|
||||
|
||||
#####################
|
||||
# Environment tests #
|
||||
#####################
|
||||
|
||||
DRIVER_UPPERCASE := $(shell echo ${DRIVER} | tr "[:lower:]" "[:upper:]")
|
||||
|
||||
ifeq (,${BUILD_KERNEL})
|
||||
BUILD_KERNEL=$(shell uname -r)
|
||||
endif
|
||||
|
||||
# Kernel Search Path
|
||||
# All the places we look for kernel source
|
||||
KSP := /lib/modules/${BUILD_KERNEL}/source \
|
||||
/lib/modules/${BUILD_KERNEL}/build \
|
||||
/usr/src/linux-${BUILD_KERNEL} \
|
||||
/usr/src/linux-$(${BUILD_KERNEL} | sed 's/-.*//') \
|
||||
/usr/src/kernel-headers-${BUILD_KERNEL} \
|
||||
/usr/src/kernel-source-${BUILD_KERNEL} \
|
||||
/usr/src/linux-$(${BUILD_KERNEL} | sed 's/\([0-9]*\.[0-9]*\)\..*/\1/') \
|
||||
/usr/src/linux \
|
||||
/usr/src/kernels/${BUILD_KERNEL} \
|
||||
/usr/src/kernels \
|
||||
${KBUILD}
|
||||
|
||||
# prune the list down to only values that exist and have an include/linux
|
||||
# sub-directory. We can't use include/config because some older kernels don't
|
||||
# have this.
|
||||
test_dir = $(shell [ -e ${dir}/include/linux ] && echo ${dir})
|
||||
KSP := $(foreach dir, ${KSP}, ${test_dir})
|
||||
|
||||
# we will use this first valid entry in the search path
|
||||
ifeq (,${KSRC})
|
||||
KSRC := $(firstword ${KSP})
|
||||
endif
|
||||
|
||||
ifeq (,${KSRC})
|
||||
$(warning *** Kernel header files not in any of the expected locations.)
|
||||
$(warning *** Install the appropriate kernel development package, e.g.)
|
||||
$(error kernel-devel, for building kernel modules and try again)
|
||||
else
|
||||
ifeq (/lib/modules/${BUILD_KERNEL}/source, ${KSRC})
|
||||
KOBJ := /lib/modules/${BUILD_KERNEL}/build
|
||||
else
|
||||
KOBJ := ${KSRC}
|
||||
endif
|
||||
endif
|
||||
|
||||
SCRIPT_PATH := ${KSRC}/scripts
|
||||
|
||||
# Version file Search Path
|
||||
VSP := ${KOBJ}/include/generated/utsrelease.h \
|
||||
${KOBJ}/include/linux/utsrelease.h \
|
||||
${KOBJ}/include/linux/version.h \
|
||||
${KOBJ}/include/generated/uapi/linux/version.h \
|
||||
/boot/vmlinuz.version.h
|
||||
|
||||
# Config file Search Path
|
||||
CSP := ${KOBJ}/include/generated/autoconf.h \
|
||||
${KOBJ}/include/linux/autoconf.h \
|
||||
/boot/vmlinuz.autoconf.h
|
||||
|
||||
# System.map Search Path (for depmod)
|
||||
MSP := ${KSRC}/System.map \
|
||||
/usr/lib/debug/boot/System.map-${BUILD_KERNEL} \
|
||||
/boot/System.map-${BUILD_KERNEL}
|
||||
|
||||
# prune the lists down to only files that exist
|
||||
test_file = $(shell [ -f ${1} ] && echo ${1})
|
||||
VSP := $(foreach file, ${VSP}, $(call test_file,${file}))
|
||||
CSP := $(foreach file, ${CSP}, $(call test_file,${file}))
|
||||
MSP := $(foreach file, ${MSP}, $(call test_file,${file}))
|
||||
|
||||
|
||||
# and use the first valid entry in the Search Paths
|
||||
ifeq (,${VERSION_FILE})
|
||||
VERSION_FILE := $(firstword ${VSP})
|
||||
endif
|
||||
|
||||
ifeq (,${CONFIG_FILE})
|
||||
CONFIG_FILE := $(firstword ${CSP})
|
||||
endif
|
||||
|
||||
ifeq (,${SYSTEM_MAP_FILE})
|
||||
SYSTEM_MAP_FILE := $(firstword ${MSP})
|
||||
endif
|
||||
|
||||
ifeq (,$(wildcard ${VERSION_FILE}))
|
||||
$(error Linux kernel source not configured - missing version header file)
|
||||
endif
|
||||
|
||||
ifeq (,$(wildcard ${CONFIG_FILE}))
|
||||
$(error Linux kernel source not configured - missing autoconf.h)
|
||||
endif
|
||||
|
||||
ifeq (,$(wildcard ${SYSTEM_MAP_FILE}))
|
||||
$(warning Missing System.map file - depmod will not check for missing symbols during module installation)
|
||||
endif
|
||||
|
||||
ifneq ($(words $(subst :, ,$(CURDIR))), 1)
|
||||
$(error Sources directory '$(CURDIR)' cannot contain spaces nor colons. Rename directory or move sources to another path)
|
||||
endif
|
||||
|
||||
########################
|
||||
# Extract config value #
|
||||
########################
|
||||
|
||||
get_config_value = $(shell ${CC} -E -dM ${CONFIG_FILE} 2> /dev/null |\
|
||||
grep -m 1 ${1} | awk '{ print $$3 }')
|
||||
|
||||
|
||||
#######################
|
||||
# Linux Version Setup #
|
||||
#######################
|
||||
|
||||
# The following command line parameter is intended for development of KCOMPAT
|
||||
# against upstream kernels such as net-next which have broken or non-updated
|
||||
# version codes in their Makefile. They are intended for debugging and
|
||||
# development purpose only so that we can easily test new KCOMPAT early. If you
|
||||
# don't know what this means, you do not need to set this flag. There is no
|
||||
# arcane magic here.
|
||||
|
||||
# Convert LINUX_VERSION into LINUX_VERSION_CODE
|
||||
ifneq (${LINUX_VERSION},)
|
||||
LINUX_VERSION_CODE=$(call get_kvercode,$(call get_kver,${LINUX_VERSION},1),$(call get_kver,${LINUX_VERSION},2),$(call get_kver,${LINUX_VERSION},3))
|
||||
endif
|
||||
|
||||
# Honor LINUX_VERSION_CODE
|
||||
ifneq (${LINUX_VERSION_CODE},)
|
||||
$(warning Forcing target kernel to build with LINUX_VERSION_CODE of ${LINUX_VERSION_CODE}$(if ${LINUX_VERSION}, from LINUX_VERSION=${LINUX_VERSION}). Do this at your own risk.)
|
||||
KVER_CODE := ${LINUX_VERSION_CODE}
|
||||
EXTRA_CFLAGS += -DLINUX_VERSION_CODE=${LINUX_VERSION_CODE}
|
||||
endif
|
||||
|
||||
# Determine SLE_KERNEL_REVISION for SuSE SLE >= 11 (needed by kcompat)
|
||||
# This assumes SuSE will continue setting CONFIG_LOCALVERSION to the string
|
||||
# appended to the stable kernel version on which their kernel is based with
|
||||
# additional versioning information (up to 3 numbers), a possible abbreviated
|
||||
# git SHA1 commit id and a kernel type, e.g. CONFIG_LOCALVERSION=-1.2.3-default
|
||||
# or CONFIG_LOCALVERSION=-999.gdeadbee-default
|
||||
# SLE >= 15SP3 added additional information about version and service pack
|
||||
# to their kernel version e.g CONFIG_LOCALVERSION=-150300.59.43.1-default
|
||||
#
|
||||
# SLE_LOCALVERSION_CODE is also exported to support legacy kcompat.h
|
||||
# definitions.
|
||||
ifeq (1,$(call get_config_value,CONFIG_SUSE_KERNEL))
|
||||
|
||||
ifneq (10,$(call get_config_value,CONFIG_SLE_VERSION))
|
||||
|
||||
CONFIG_LOCALVERSION := $(call get_config_value,CONFIG_LOCALVERSION)
|
||||
LOCALVERSION := $(shell echo ${CONFIG_LOCALVERSION} | \
|
||||
cut -d'-' -f2 | sed 's/\.g[[:xdigit:]]\{7\}//')
|
||||
LOCALVER_A := $(shell echo ${LOCALVERSION} | cut -d'.' -f1)
|
||||
ifeq ($(shell test ${LOCALVER_A} -gt 65535; echo $$?),0)
|
||||
LOCAL_VER_MAJOR := $(shell echo ${LOCALVER_A:0:3})
|
||||
LOCAL_VER_MINOR := $(shell echo ${LOCALVER_A:3:3})
|
||||
LOCALVER_B := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f2)
|
||||
LOCALVER_C := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f3)
|
||||
LOCALVER_D := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f4)
|
||||
SLE_LOCALVERSION_CODE := $(shell expr ${LOCALVER_B} \* 65536 + \
|
||||
0${LOCALVER_C} \* 256 + 0${LOCALVER_D})
|
||||
EXTRA_CFLAGS += -DSLE_LOCALVERSION_CODE=${SLE_LOCALVERSION_CODE}
|
||||
EXTRA_CFLAGS += -DSLE_KERNEL_REVISION=${LOCALVER_B}
|
||||
else
|
||||
LOCALVER_B := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f2)
|
||||
LOCALVER_C := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f3)
|
||||
SLE_LOCALVERSION_CODE := $(shell expr ${LOCALVER_A} \* 65536 + \
|
||||
0${LOCALVER_B} \* 256 + 0${LOCALVER_C})
|
||||
EXTRA_CFLAGS += -DSLE_LOCALVERSION_CODE=${SLE_LOCALVERSION_CODE}
|
||||
EXTRA_CFLAGS += -DSLE_KERNEL_REVISION=${LOCALVER_A}
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# Check if it is Oracle Linux UEK kernel and take release patch number from it
|
||||
ifneq (,$(findstring uek,${BUILD_KERNEL}))
|
||||
EXTRAVERSION := $(shell echo ${BUILD_KERNEL} | cut -s -d '-' -f2-)
|
||||
UEK_RELEASE_NUMBER := $(shell echo ${EXTRAVERSION} | cut -s -d '.' -f1)
|
||||
UEK_MINOR_RELEASE_NUMBER := $(shell echo ${EXTRAVERSION} | cut -s -d '.' -f2)
|
||||
EXTRA_CFLAGS += -DUEK_RELEASE_NUMBER=${UEK_RELEASE_NUMBER}
|
||||
EXTRA_CFLAGS += -DUEK_MINOR_RELEASE_NUMBER=${UEK_MINOR_RELEASE_NUMBER}
|
||||
endif
|
||||
|
||||
EXTRA_CFLAGS += ${CFLAGS_EXTRA}
|
||||
|
||||
# get the kernel version - we use this to find the correct install path
|
||||
KVER := $(shell ${CC} ${EXTRA_CFLAGS} -E -dM ${VERSION_FILE} | grep UTS_RELEASE | \
|
||||
awk '{ print $$3 }' | sed 's/\"//g')
|
||||
|
||||
# assume source symlink is the same as build, otherwise adjust KOBJ
|
||||
ifneq (,$(wildcard /lib/modules/${KVER}/build))
|
||||
ifneq (${KSRC},$(call readlink,/lib/modules/${KVER}/build))
|
||||
KOBJ=/lib/modules/${KVER}/build
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq (${KVER_CODE},)
|
||||
KVER_CODE := $(shell ${CC} ${EXTRA_CFLAGS} -E -dM ${VSP} 2> /dev/null |\
|
||||
grep -m 1 LINUX_VERSION_CODE | awk '{ print $$3 }' | sed 's/\"//g')
|
||||
endif
|
||||
|
||||
# minimum_kver_check
|
||||
#
|
||||
# helper function to provide uniform output for different drivers to abort the
|
||||
# build based on kernel version check. Usage: "$(call minimum_kver_check,2,6,XX)".
|
||||
define _minimum_kver_check
|
||||
ifeq (0,$(shell [ ${KVER_CODE} -lt $(call get_kvercode,${1},${2},${3}) ]; echo "$$?"))
|
||||
$$(warning *** Aborting the build.)
|
||||
$$(error This driver is not supported on kernel versions older than ${1}.${2}.${3})
|
||||
endif
|
||||
endef
|
||||
minimum_kver_check = $(eval $(call _minimum_kver_check,${1},${2},${3}))
|
||||
|
||||
#############################
|
||||
# kcompat definitions setup #
|
||||
#############################
|
||||
|
||||
# In most cases, kcompat flags can be checked within the driver source files
|
||||
# using simple CPP checks. However, it may be necessary to check for a flag
|
||||
# value within the Makefile for some specific edge cases. For example, if an
|
||||
# entire feature ought to be excluded on some kernels due to missing
|
||||
# functionality.
|
||||
#
|
||||
# To support this, kcompat_defs.h is compiled and converted into a word list
|
||||
# that can be checked to determine whether a given kcompat feature flag will
|
||||
# be defined for this kernel.
|
||||
#
|
||||
# KCOMPAT_DEFINITIONS holds the set of all macros which are defined. Note
|
||||
# this does include a large number of standard/builtin definitions.
|
||||
#
|
||||
# Use is_kcompat_defined as a $(call) function to check whether a given flag
|
||||
# is defined or undefined. For example:
|
||||
#
|
||||
# ifeq ($(call is_kcompat_defined,HAVE_FEATURE_FLAG),1)
|
||||
#
|
||||
# ifneq ($(call is_kcompat_defined,HAVE_FEATURE_FLAG),1)
|
||||
#
|
||||
# The is_kcompat_defined function returns 1 if the macro name is defined,
|
||||
# and the empty string otherwise.
|
||||
#
|
||||
# There is no mechanism to extract the value of the kcompat definition.
|
||||
# Supporting this would be non-trivial as Make does not have a map variable
|
||||
# type.
|
||||
#
|
||||
# Note that only the new layout is supported. Legacy definitions in
|
||||
# kcompat.h are not supported. If you need to check one of these, please
|
||||
# refactor it into the new layout.
|
||||
|
||||
ifneq ($(wildcard ./kcompat_defs.h),)
|
||||
KCOMPAT_DEFINITIONS := $(shell ${CC} ${EXTRA_CFLAGS} -E -dM \
|
||||
-I${KOBJ}/include \
|
||||
-I${KOBJ}/include/generated/uapi \
|
||||
kcompat_defs.h | awk '{ print $$2 }')
|
||||
|
||||
is_kcompat_defined = $(if $(filter ${1},${KCOMPAT_DEFINITIONS}),1,)
|
||||
else
|
||||
KCOMPAT_DEFINITIONS :=
|
||||
is_kcompat_defined =
|
||||
endif
|
||||
|
||||
################
|
||||
# Manual Pages #
|
||||
################
|
||||
|
||||
MANSECTION = 7
|
||||
|
||||
ifeq (,${MANDIR})
|
||||
# find the best place to install the man page
|
||||
MANPATH := $(shell (manpath 2>/dev/null || echo $MANPATH) | sed 's/:/ /g')
|
||||
ifneq (,${MANPATH})
|
||||
# test based on inclusion in MANPATH
|
||||
test_dir = $(findstring ${dir}, ${MANPATH})
|
||||
else
|
||||
# no MANPATH, test based on directory existence
|
||||
test_dir = $(shell [ -e ${dir} ] && echo ${dir})
|
||||
endif
|
||||
# our preferred install path
|
||||
# should /usr/local/man be in here ?
|
||||
MANDIR := /usr/share/man /usr/man
|
||||
MANDIR := $(foreach dir, ${MANDIR}, ${test_dir})
|
||||
MANDIR := $(firstword ${MANDIR})
|
||||
endif
|
||||
ifeq (,${MANDIR})
|
||||
# fallback to /usr/man
|
||||
MANDIR := /usr/man
|
||||
endif
|
||||
|
||||
####################
|
||||
# CCFLAGS variable #
|
||||
####################
|
||||
|
||||
# set correct CCFLAGS variable for kernels older than 2.6.24
|
||||
ifeq (0,$(shell [ ${KVER_CODE} -lt $(call get_kvercode,2,6,24) ]; echo $$?))
|
||||
CCFLAGS_VAR := EXTRA_CFLAGS
|
||||
else
|
||||
CCFLAGS_VAR := ccflags-y
|
||||
endif
|
||||
|
||||
#################
|
||||
# KBUILD_OUTPUT #
|
||||
#################
|
||||
|
||||
# Only set KBUILD_OUTPUT if the real paths of KOBJ and KSRC differ
|
||||
ifneq ($(call readlink,${KSRC}),$(call readlink,${KOBJ}))
|
||||
export KBUILD_OUTPUT ?= ${KOBJ}
|
||||
endif
|
||||
|
||||
############################
|
||||
# Module Install Directory #
|
||||
############################
|
||||
|
||||
# Default to using updates/drivers/net/ethernet/jm/ path, since depmod since
|
||||
# v3.1 defaults to checking updates folder first, and only checking kernels/
|
||||
# and extra afterwards. We use updates instead of kernel/* due to desire to
|
||||
# prevent over-writing built-in modules files.
|
||||
export INSTALL_MOD_DIR ?= updates/drivers/net/ethernet/jm/${DRIVER}
|
||||
|
||||
#################
|
||||
# Auxiliary Bus #
|
||||
#################
|
||||
|
||||
# If the check_aux_bus script exists, then this driver depends on the
|
||||
# auxiliary module. Run the script to determine if we need to include
|
||||
# auxiliary files with this build.
|
||||
CHECK_AUX_BUS ?= ./scripts/check_aux_bus.sh
|
||||
ifneq ($(call test_file,${CHECK_AUX_BUS}),)
|
||||
NEED_AUX_BUS := $(shell ${CHECK_AUX_BUS} --ksrc="${KSRC}" --build-kernel="${BUILD_KERNEL}" >/dev/null 2>&1; echo $$?)
|
||||
endif # check_aux_bus exists
|
||||
|
||||
# The out-of-tree auxiliary module we ship should be moved into this
|
||||
# directory as part of installation.
|
||||
export INSTALL_AUX_DIR ?= updates/drivers/net/ethernet/jm/auxiliary
|
||||
|
||||
# If we're installing auxiliary bus out-of-tree, the following steps are
|
||||
# necessary to ensure the relevant files get put in place.
|
||||
AUX_BUS_HEADER ?= linux/auxiliary_bus.h
|
||||
ifeq (${NEED_AUX_BUS},2)
|
||||
define auxiliary_post_install
|
||||
install -D -m 644 Module.symvers ${INSTALL_MOD_PATH}/lib/modules/${KVER}/extern-symvers/jm_auxiliary.symvers
|
||||
install -d ${INSTALL_MOD_PATH}/lib/modules/${KVER}/${INSTALL_AUX_DIR}
|
||||
install -D -m 644 jm_auxiliary.ko ${INSTALL_MOD_PATH}/lib/modules/${KVER}/${INSTALL_AUX_DIR}/
|
||||
install -D -m 644 ${AUX_BUS_HEADER} ${INSTALL_MOD_PATH}/${KSRC}/include/linux/auxiliary_bus.h
|
||||
endef
|
||||
else
|
||||
auxiliary_post_install =
|
||||
endif
|
||||
|
||||
ifeq (${NEED_AUX_BUS},2)
|
||||
define auxiliary_post_uninstall
|
||||
rm -f ${INSTALL_MOD_PATH}/lib/modules/${KVER}/extern-symvers/jm_auxiliary.symvers
|
||||
rm -f ${INSTALL_MOD_PATH}/lib/modules/${KVER}/${INSTALL_AUX_DIR}/jm_auxiliary.ko
|
||||
rm -f ${INSTALL_MOD_PATH}/${KSRC}/include/linux/auxiliary_bus.h
|
||||
endef
|
||||
else
|
||||
auxiliary_post_uninstall =
|
||||
endif
|
||||
|
||||
ifeq (${NEED_AUX_BUS},2)
|
||||
EXTRA_CFLAGS += -DUSE_JM_AUX_BUS
|
||||
endif
|
||||
######################
|
||||
# Kernel Build Macro #
|
||||
######################
|
||||
|
||||
# kernel build function
|
||||
# ${1} is the kernel build target
|
||||
# ${2} may contain any extra rules to pass directly to the sub-make process
|
||||
#
|
||||
# This function is expected to be executed by
|
||||
# @+$(call kernelbuild,<target>,<extra parameters>)
|
||||
# from within a Makefile recipe.
|
||||
#
|
||||
# The following variables are expected to be defined for its use:
|
||||
# CCFLAGS_VAR -- the CCFLAGS variable to set extra CFLAGS
|
||||
# EXTRA_CFLAGS -- a set of extra CFLAGS to pass into the ccflags-y variable
|
||||
# KSRC -- the location of the kernel source tree to build against
|
||||
# DRIVER_UPPERCASE -- the uppercase name of the kernel module, set from DRIVER
|
||||
# W -- if set, enables the W= kernel warnings options
|
||||
# C -- if set, enables the C= kernel sparse build options
|
||||
#
|
||||
kernelbuild = ${MAKE} ${CCFLAGS_VAR}="${EXTRA_CFLAGS}" \
|
||||
-C "${KSRC}" \
|
||||
CONFIG_${DRIVER_UPPERCASE}=m \
|
||||
M="${CURDIR}" \
|
||||
$(if ${W},W="${W}") \
|
||||
$(if ${C},C="${C}") \
|
||||
$(if ${NEED_AUX_BUS},NEED_AUX_BUS="${NEED_AUX_BUS}") \
|
||||
${2} ${1}
|
2441
LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete.c
Normal file
2441
LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-core/crete.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,736 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#ifndef _CRETE_H_
|
||||
#define _CRETE_H_
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/timecounter.h>
|
||||
#include <linux/net_tstamp.h>
|
||||
#include <linux/ptp_clock_kernel.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/version.h>
|
||||
#include <net/dst_metadata.h>
|
||||
#ifndef USE_JM_AUX_BUS
|
||||
#include <linux/auxiliary_bus.h>
|
||||
#else
|
||||
#include "linux/auxiliary_bus.h"
|
||||
#endif
|
||||
#include "kcompat_std_defs.h"
|
||||
#include "rdma.h"
|
||||
#include "crete_txrx.h"
|
||||
#include "crete_sriov.h"
|
||||
#include "crete_eswitch.h"
|
||||
#include "crete_dcb_nl.h"
|
||||
#include "crete_lag.h"
|
||||
#include "crete_debugfs_statistics.h"
|
||||
/*micro filed*/
|
||||
#define MAX_MSIX_ENTRIES 10
|
||||
#define MAX_Q_VECTORS 8
|
||||
|
||||
#define CRETE_MAX_TX_QUEUES 8
|
||||
#define CRETE_MAX_RX_QUEUES 8
|
||||
|
||||
#define CRETE_DEFAULT_TXD 256
|
||||
#define CRETE_DEFAULT_TX_WORK 128
|
||||
#define CRETE_MIN_TXD 80
|
||||
#define CRETE_MAX_TXD 4096
|
||||
|
||||
#define CRETE_DEFAULT_RXD 256
|
||||
#define CRETE_MIN_RXD 80
|
||||
#define CRETE_MAX_RXD 4096
|
||||
|
||||
#define CRETE_DEFAULT_ITR 3 /* dynamic */
|
||||
#define CRETE_MAX_ITR_USECS 10000
|
||||
#define CRETE_MIN_ITR_USECS 10
|
||||
#define CRETE_Q_VECTORS 1
|
||||
|
||||
#define CRETE_ETH_PKT_HDR_PAD (ETH_HLEN + ETH_FCS_LEN)
|
||||
|
||||
/* As per the EAS the maximum supported size is 9.5KB (9728 bytes) */
|
||||
#define MAX_JUMBO_FRAME_SIZE 0x2600
|
||||
#define MAX_STD_JUMBO_FRAME_SIZE 9216
|
||||
|
||||
/* Supported Rx Buffer Sizes */
|
||||
#define CRETE_RXBUFFER_256 256
|
||||
#define CRETE_RXBUFFER_1536 1536
|
||||
#define CRETE_RXBUFFER_2048 2048
|
||||
#define CRETE_TS_HDR_LEN 16
|
||||
#define ALIGN_TO_DW(a) (((a) + 3ULL) & (~3))
|
||||
#define CRETE_CMD_WQ_MAX_NAME 32
|
||||
|
||||
/* device desc offset */
|
||||
#define CRETE_JDH_OFFSET (CRETE_LEGACY_RESV)
|
||||
#define CRETE_JND_OFFSET (CRETE_JDH_OFFSET + sizeof(struct crete_desc_hdr))
|
||||
#define CRETE_JRD_OFFSET (CRETE_JND_OFFSET + sizeof(struct crete_ndc_dpt))
|
||||
#define CRETE_CAP_OFFSET 8
|
||||
|
||||
enum {
|
||||
CRETE_FLAG_DISABLE_ALL_ADEV = 1 << 0,
|
||||
CRETE_PAGE_MODE = 1 << 1,
|
||||
CRETE_FLAG_HAS_MSIX = 1 << 13,
|
||||
};
|
||||
|
||||
#define CRETE_LEGACY_RESV 0x0
|
||||
#define CRETE_MAGIC_NUM 0xdeadbeef
|
||||
|
||||
#define CRETE_EVENT_VECTOR 0
|
||||
|
||||
#define CRETE_CMD_DATA_BLOCK_SIZE 512
|
||||
|
||||
enum crete_coredev_type {
|
||||
CRETE_COREDEV_PF,
|
||||
CRETE_COREDEV_VF,
|
||||
CRETE_COREDEV_SF,
|
||||
};
|
||||
|
||||
|
||||
enum crete_device_type {
|
||||
CRETE_DEVICE_CRETE,
|
||||
CRETE_DEVICE_PNIC,
|
||||
CRETE_DEVICE_RNIC,
|
||||
CRETE_DEVICE_FAKE,
|
||||
};
|
||||
|
||||
enum {
|
||||
CRETE_PCI_DEV_IS_VF = 1 << 0,
|
||||
};
|
||||
|
||||
#define CRETE_ADEV_NAME "crete_core"
|
||||
|
||||
/*enum filed*/
|
||||
enum crete_state_t {
|
||||
__CRETE_TESTING,
|
||||
__CRETE_RESETING,
|
||||
__CRETE_DOWN,
|
||||
};
|
||||
|
||||
/* Device Capability type */
|
||||
enum crete_cap_type {
|
||||
CRETE_NET_CONF_CAP = 2,
|
||||
CRETE_RDMA_CONF_CAP = 3,
|
||||
CRETE_OFFLOAD_CONF_CAP = 4,
|
||||
CRETE_RES_CONF_CAP = 5,
|
||||
CRETE_DEVS_CONF_CAP = 6,
|
||||
CRETE_SHARES_DB_CAP = 7,
|
||||
CRETE_CAP_MAX,
|
||||
};
|
||||
|
||||
struct crete_init_seg {
|
||||
uint16_t fw_ver_minor;
|
||||
uint16_t fw_ver_major;
|
||||
uint16_t fw_revision;
|
||||
uint16_t cmd_interface_rev;
|
||||
uint8_t cp_status;
|
||||
uint8_t cp_caps;
|
||||
uint8_t dev_status;
|
||||
uint8_t reset_dev;
|
||||
uint32_t cmd_path_db;
|
||||
uint32_t cmd_path_entry[16];
|
||||
uint32_t resv1[8];
|
||||
uint32_t event_buffer[8];
|
||||
uint32_t event_buffer_addr_low;
|
||||
uint32_t event_buffer_addr_hi;
|
||||
uint8_t event_busy;
|
||||
uint8_t event_buffer_size;
|
||||
uint16_t event_vector;
|
||||
uint32_t event_credit_doorbell;
|
||||
uint16_t resv2;
|
||||
uint16_t aq_queue_size;
|
||||
uint32_t aq_queue_db;
|
||||
uint32_t aq_base_addr_low;
|
||||
uint32_t aq_base_addr_hi;
|
||||
uint32_t shared_res_lock;
|
||||
uint32_t shared_res_db;
|
||||
uint32_t extra_admin_db;
|
||||
uint32_t resv3[13];
|
||||
uint32_t timestamp[2];
|
||||
} __packed;
|
||||
|
||||
struct cmd_info {
|
||||
uint32_t owner:1;
|
||||
uint32_t out_inline:1;
|
||||
uint32_t in_inline:1;
|
||||
uint32_t event_notify:1;
|
||||
uint32_t status:4;
|
||||
uint32_t sig:8;
|
||||
uint32_t cmd_encap_type:8;
|
||||
uint32_t cid:8;
|
||||
};
|
||||
|
||||
struct crete_cmd_entry {
|
||||
uint32_t in_len;
|
||||
uint32_t out_len;
|
||||
uint64_t in_ptr;
|
||||
uint64_t out_ptr;
|
||||
uint8_t inline_data[36];
|
||||
union {
|
||||
struct cmd_info cmd_info;
|
||||
uint32_t cmd_info_data;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct crete_cmd_prot_block {
|
||||
u8 sig;
|
||||
u8 block_num;
|
||||
u8 rsvd0;
|
||||
u8 cid;
|
||||
uint32_t cmd_data_len;//CRETE_CMD_DATA_BLOCK_SIZE
|
||||
uint64_t next;
|
||||
uint32_t next_len;
|
||||
uint32_t cmd_data[];
|
||||
} __packed;
|
||||
|
||||
struct crete_cmd_mailbox {
|
||||
void *buf;
|
||||
dma_addr_t dma;
|
||||
struct crete_cmd_mailbox *next;
|
||||
};
|
||||
struct crete_cmd_msg {
|
||||
struct list_head list;
|
||||
u32 msg_mode;
|
||||
u32 len;
|
||||
struct crete_cmd_mailbox *next;
|
||||
u8 inline_data[36]; //inline bd Optimize todo
|
||||
}__aligned(8);
|
||||
|
||||
#define CRETE_MAX_COMMANDS 32
|
||||
struct crete_cmd_work_ent {
|
||||
unsigned long state;
|
||||
struct crete_cmd_msg *inb;
|
||||
struct crete_cmd_msg *outb;
|
||||
void *out;
|
||||
int out_size;
|
||||
int idx;
|
||||
struct completion handling;
|
||||
struct completion done;
|
||||
struct crete_cmd *cmd;
|
||||
struct work_struct work;
|
||||
struct crete_cmd_entry *lay;
|
||||
int ret;
|
||||
u8 status;//fw return cmd status
|
||||
u16 cmd_id;
|
||||
bool polling;
|
||||
u64 ts1;
|
||||
u64 ts2;
|
||||
/* Track the max comp handlers */
|
||||
refcount_t refcnt;
|
||||
};
|
||||
struct crete_cmd {
|
||||
struct crete_nb nb;
|
||||
u8 mode;
|
||||
u8 poll_mode;
|
||||
void *cmd_buf;
|
||||
dma_addr_t cmd_dma;
|
||||
u32 cmd_size;
|
||||
u32 cmd_stride;
|
||||
struct dma_pool *pool;
|
||||
int max_cmds;
|
||||
unsigned long bitmask;
|
||||
char wq_name[CRETE_CMD_WQ_MAX_NAME];
|
||||
struct workqueue_struct *wq;
|
||||
struct semaphore sem;
|
||||
spinlock_t alloc_lock;
|
||||
struct crete_cmd_work_ent *ent_arr[CRETE_MAX_COMMANDS];
|
||||
};
|
||||
|
||||
/* for test qp create */
|
||||
struct crete_qbase_info {
|
||||
void *va;
|
||||
dma_addr_t pa;
|
||||
};
|
||||
|
||||
struct crete_queue_info {
|
||||
uint8_t rx_qid;
|
||||
uint16_t q_size;
|
||||
uint16_t vec[2];
|
||||
struct crete_qbase_info sq[2];
|
||||
struct crete_qbase_info cq[2];
|
||||
};
|
||||
/*
|
||||
*Device Capability Descriptor
|
||||
*Device Capability Descriptor Header
|
||||
*/
|
||||
struct crete_desc_hdr {
|
||||
uint32_t magic;
|
||||
uint32_t cap_cnt:8;
|
||||
uint32_t len:12;
|
||||
uint32_t offset:12;
|
||||
};
|
||||
|
||||
// net device configuration descriptor,cap_type = 2
|
||||
struct crete_ndc_dpt {
|
||||
uint32_t type:8;
|
||||
uint32_t resv:24;
|
||||
uint32_t len:12;
|
||||
uint32_t offset:20;
|
||||
};
|
||||
|
||||
// Rdma Device Configuration Descriptor,cap_type = 3
|
||||
struct crete_rdma_cfg_desc {
|
||||
uint32_t cap_type:8;
|
||||
uint32_t resv:24;
|
||||
uint32_t len:12;
|
||||
uint32_t offset:20;
|
||||
};
|
||||
|
||||
// Offload Configuration Descriptor,cap_type = 4
|
||||
struct crete_offload_cfg_desc {
|
||||
uint32_t cap_type:8;
|
||||
uint32_t resv:24;
|
||||
uint32_t len:12;
|
||||
uint32_t offset:20;
|
||||
};
|
||||
|
||||
|
||||
// resource configuration descriptor,cap_type = 5
|
||||
struct crete_rc_dpt {
|
||||
uint32_t type:8;
|
||||
uint32_t ru_size:12;
|
||||
uint32_t ru_max:12;
|
||||
uint32_t len:12;
|
||||
uint32_t offset:20;
|
||||
};
|
||||
|
||||
//Device-specific Configuration Descriptor,cap_type = 6
|
||||
struct crete_devs_dpt {
|
||||
uint32_t cap_type:8;
|
||||
uint32_t resv:24;
|
||||
uint32_t len:12;
|
||||
uint32_t offset:20;
|
||||
};
|
||||
|
||||
//Shared Data Descriptor,cap_type = 7
|
||||
struct crete_shared_dpt {
|
||||
uint32_t cap_type:8;
|
||||
uint32_t len:24;
|
||||
uint32_t offset;
|
||||
};
|
||||
|
||||
|
||||
/* hw */
|
||||
struct crete_hw {
|
||||
struct crete_init_seg __iomem *io_addr;
|
||||
struct crete_desc_hdr jdh;
|
||||
struct crete_ndc_dpt jnd;
|
||||
struct crete_rdma_cfg_desc rdma_desc;
|
||||
struct crete_offload_cfg_desc offload_desc;
|
||||
struct crete_rc_dpt jrd;
|
||||
struct crete_devs_dpt dev_spec_desc;
|
||||
struct crete_shared_dpt share_data_desc;
|
||||
};
|
||||
|
||||
struct crete_aux_dev {
|
||||
struct crete_core_dev *core_dev;
|
||||
struct auxiliary_device adev;
|
||||
int idx;
|
||||
};
|
||||
|
||||
#define CRETE_MAX_UC_ADDRS 4
|
||||
#define CRETE_MAX_MC_ADDRS 16
|
||||
|
||||
|
||||
#define L2_SET_RX_MASK_REQ_MASK_MCAST 0x1UL
|
||||
#define L2_SET_RX_MASK_REQ_MASK_ALL_MCAST 0x2UL
|
||||
#define L2_SET_RX_MASK_REQ_MASK_BCAST 0x4UL
|
||||
#define L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS 0x8UL
|
||||
|
||||
struct crete_priv {
|
||||
struct crete_core_dev *coredev;
|
||||
struct crete_esw_rep *rep;
|
||||
struct net_device *netdev;
|
||||
struct workqueue_struct *wq;
|
||||
struct work_struct set_rx_mode_work;
|
||||
struct crete_dcbx dcbx;
|
||||
struct crete_dcbx_dp dcbx_dp;
|
||||
|
||||
/* vport rx mode */
|
||||
u32 rx_mask;
|
||||
__le64 fw_l2_filter_id[CRETE_MAX_UC_ADDRS];
|
||||
/* index 0 always dev_addr */
|
||||
u16 uc_filter_count;
|
||||
u8 *uc_list;
|
||||
|
||||
u8 *mc_list;
|
||||
int mc_list_size;
|
||||
int mc_list_count;
|
||||
|
||||
int vlan_range_num;
|
||||
};
|
||||
|
||||
struct crete_debugfs_entries {
|
||||
struct dentry *dbg_root;
|
||||
struct dentry *lag_debugfs;
|
||||
struct dentry *statistics_debugfs;
|
||||
};
|
||||
|
||||
struct crete_irq_info {
|
||||
char name[IFNAMSIZ + 2];
|
||||
irq_handler_t handler;
|
||||
unsigned int vector;
|
||||
u8 requested:1;
|
||||
u8 have_cpumask:1;
|
||||
};
|
||||
|
||||
struct crete_pf_info {
|
||||
u16 fw_fid;
|
||||
u16 port_id;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
u32 first_vf_id;
|
||||
u16 active_vfs;
|
||||
u16 registered_vfs;
|
||||
u16 max_vfs;
|
||||
|
||||
void *hwrm_cmd_req_addr[4];
|
||||
dma_addr_t hwrm_cmd_req_dma_addr[4];
|
||||
struct crete_vf_info *vf;
|
||||
|
||||
struct kobject *config;
|
||||
struct kobject *groups_config;
|
||||
struct crete_sriov_vf_sysfs *vf_sysfs;
|
||||
};
|
||||
|
||||
struct rdma_dev_adapt {
|
||||
unsigned int flags;
|
||||
unsigned int priv_flags;
|
||||
unsigned int bar_offset;
|
||||
unsigned int bar_len;
|
||||
phys_addr_t uar_base;
|
||||
unsigned int uar_size;
|
||||
void __iomem *reg_addr; /*bar addr*/
|
||||
__le32 *cmd_db_reg; /* cmd db addr*/
|
||||
__le32 __iomem *eq_db_reg;
|
||||
struct mutex intf_state_mutex;
|
||||
unsigned int vector_base;
|
||||
unsigned int vector_num;
|
||||
};
|
||||
|
||||
struct crete_qp_context {
|
||||
__le16 rx_qid; /* must be even */
|
||||
__le16 event_credit;
|
||||
__le16 rx_sq_vq_size; /* vnet rx vq size */
|
||||
__le16 rx_cq_size; /* unless for vnet */
|
||||
__le16 tx_sq_vq_size; /* tx vq size for vnet */
|
||||
__le16 tx_cq_size; /* useless for vnet */
|
||||
__le16 rx_queue_vec; /* rx queue interrupt vector */
|
||||
__le16 tx_queue_vec; /* tx queue interrupt vector */
|
||||
__le64 rx_sq_desc_base; /* rx queue desc base address for vnet */
|
||||
__le64 rx_cq_used_base; /* rx cq address ,rx used ring address for vnet */
|
||||
__le64 tx_sq_desc_base; /* tx sq address, tx queue desc address for vnet */
|
||||
__le64 tx_cq_used_base; /* tx cq address, tx queue used ring address for vnet */
|
||||
};
|
||||
|
||||
struct crete_queue_context {
|
||||
__le16 qid; /* must be even */
|
||||
__le16 queue_size; /* vnet io vq size */
|
||||
__le16 cq_size; /* vnet cq size */
|
||||
__le16 queue_vec; /*queue interrupt vector */
|
||||
__le16 resv; /*reserved */
|
||||
__le64 queue_desc_base; /* rx queue desc base address for vnet */
|
||||
__le64 queue_used_base; /* rx cq address ,rx used ring address for vnet */
|
||||
};
|
||||
|
||||
struct crete_core_qpcap {
|
||||
u16 max_queue_size;
|
||||
u8 max_qp_num;
|
||||
u8 ctrl_queue_size;
|
||||
};
|
||||
|
||||
struct crete_core_cap {
|
||||
struct crete_core_qpcap qpcap;
|
||||
__le64 hw_features;
|
||||
__le64 driver_features;
|
||||
// pf core cap need more
|
||||
};
|
||||
|
||||
struct crete_qp_cap {
|
||||
u8 ctrl_queue_size;
|
||||
u8 max_qp_num;
|
||||
__le16 max_queue_size;
|
||||
} __packed;
|
||||
|
||||
struct crete_txq_stats {
|
||||
struct u64_stats_sync syncp;
|
||||
u64 packets;
|
||||
u64 bytes;
|
||||
u64 kicks;
|
||||
};
|
||||
|
||||
struct crete_rxq_stats {
|
||||
struct u64_stats_sync syncp;
|
||||
u64 packets;
|
||||
u64 bytes;
|
||||
u64 drops;
|
||||
u64 kicks;
|
||||
};
|
||||
|
||||
#define CRETE_TXQ_STATS(m) offsetof(struct crete_txq_stats, m)
|
||||
#define CRETE_RXQ_STATS(m) offsetof(struct crete_rxq_stats, m)
|
||||
|
||||
struct crete_core_dev {
|
||||
#define CRETE_MAX_MSIX_NUM 4096U
|
||||
spinlock_t lock;
|
||||
struct device *device;
|
||||
void __iomem *db_base;
|
||||
struct pci_dev *pdev;
|
||||
|
||||
struct crete_core_cap cap;
|
||||
struct crete_txring_info *txring;
|
||||
u16 *txring_mapping;
|
||||
// u16 txring_size;
|
||||
struct crete_rxring_info *rxring;
|
||||
u16 *rxring_mapping;
|
||||
// u16 rxring_size;
|
||||
u16 ring_size;
|
||||
// ring parameters
|
||||
u32 rx_buf_size;
|
||||
u32 rx_buf_use_size; /* useable size */
|
||||
u16 rx_offset;
|
||||
u16 rx_dma_offset;
|
||||
|
||||
struct crete_db *db;
|
||||
//struct crete_core_cap *cap;
|
||||
struct crete_napi *jnapi;
|
||||
struct crete_rxcp_ring_info *rxcpring;
|
||||
struct crete_txcp_ring_info *txcpring;
|
||||
|
||||
u16 max_qp_num;
|
||||
unsigned long state;
|
||||
|
||||
struct net_device *netdev;
|
||||
u64 netdev_features;
|
||||
u64 offload_features;
|
||||
unsigned int flags;
|
||||
u32 rss_queues;
|
||||
u8 __iomem *io_addr;
|
||||
phys_addr_t bar_addr; //for further consider
|
||||
|
||||
struct crete_hw hw;
|
||||
struct crete_queue_info q_info; // for create qp test
|
||||
struct crete_aux_dev **adev;
|
||||
int adev_idx;
|
||||
struct crete_irq_info *irq_info;
|
||||
struct crete_cmd cmd;
|
||||
struct crete_event_irq *event_irq;
|
||||
u16 irq_num;
|
||||
unsigned long irqbit[BITS_TO_LONGS(CRETE_MAX_MSIX_NUM)];
|
||||
struct msix_entry *msix_ent;
|
||||
enum crete_coredev_type coredev_type;
|
||||
enum crete_device_type device_type;
|
||||
struct crete_pf_info pf;
|
||||
struct crete_vf_info vf;
|
||||
bool sriov_cfg;
|
||||
|
||||
struct jm_rdma_core rdma_coredev;
|
||||
struct rdma_dev_adapt rdma_adp;
|
||||
|
||||
struct crete_eswitch *eswitch;
|
||||
struct crete_lag_cap lag_cap;
|
||||
struct crete_debugfs_entries dbg;
|
||||
struct crete_lag *lag_dev;
|
||||
struct crete_debugfs_statistics *debugfs_statis;
|
||||
u16 sfi_id;
|
||||
u16 lag_enable;
|
||||
};
|
||||
|
||||
|
||||
|
||||
enum crete_feature_type {
|
||||
CRETE_FEATURE_NETDEV,
|
||||
CRETE_FEATURE_OFFLOAD
|
||||
};
|
||||
|
||||
static inline unsigned int crete_rd32(struct crete_core_dev *p, u32 reg)
|
||||
{
|
||||
u8 __iomem *ioaddr = READ_ONCE(p->io_addr);
|
||||
u32 value = 0;
|
||||
|
||||
value = readl(&ioaddr[reg]);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static inline void crete_ioread32(void __iomem *addr, void *buffer,
|
||||
unsigned int count)
|
||||
{
|
||||
int i = 0;
|
||||
u32 *buf = buffer;
|
||||
u8 __iomem *address = addr;
|
||||
|
||||
if (count) {
|
||||
for (i = 0; i < count; i++)
|
||||
readsl(address + i * 4, buf++, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void crete_iowrite32(void __iomem *addr, void *buffer,
|
||||
unsigned int count)
|
||||
{
|
||||
int i = 0;
|
||||
u32 *buf = buffer;
|
||||
u8 __iomem *address = addr;
|
||||
|
||||
if (count) {
|
||||
for (i = 0; i < count; i++)
|
||||
writesl(address + i * 4, buf++, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static inline struct device *crete_hw_to_dev(struct crete_hw *hw)
|
||||
{
|
||||
struct crete_core_dev *core_dev = container_of(hw, struct crete_core_dev, hw);
|
||||
|
||||
return &core_dev->pdev->dev;
|
||||
}
|
||||
int crete_adev_idx_alloc(void);
|
||||
void crete_adev_idx_free(int idx);
|
||||
static inline bool crete_sriov_is_enabled(struct crete_core_dev *dev)
|
||||
{
|
||||
return pci_num_vf(dev->pdev) ? true : false;
|
||||
}
|
||||
|
||||
static inline bool crete_core_is_pf(const struct crete_core_dev *dev)
|
||||
{
|
||||
return dev->coredev_type == CRETE_COREDEV_PF;
|
||||
}
|
||||
|
||||
static inline bool crete_core_is_vf(const struct crete_core_dev *dev)
|
||||
{
|
||||
return dev->coredev_type == CRETE_COREDEV_VF;
|
||||
}
|
||||
|
||||
static inline bool crete_have_rdma_cap(const struct crete_core_dev *dev)
|
||||
{
|
||||
return dev->hw.rdma_desc.cap_type == CRETE_RDMA_CONF_CAP;
|
||||
}
|
||||
|
||||
static inline bool crete_have_net_cap(const struct crete_core_dev *dev)
|
||||
{
|
||||
return dev->hw.jnd.type == CRETE_NET_CONF_CAP;
|
||||
}
|
||||
|
||||
static inline u16 fw_ver_maj(struct crete_core_dev *dev)
|
||||
{
|
||||
struct crete_hw *hw = &dev->hw;
|
||||
|
||||
return readw(&hw->io_addr->fw_ver_major);
|
||||
}
|
||||
|
||||
static inline u16 fw_ver_min(struct crete_core_dev *dev)
|
||||
{
|
||||
struct crete_hw *hw = &dev->hw;
|
||||
|
||||
return readw(&hw->io_addr->fw_ver_minor);
|
||||
}
|
||||
|
||||
static inline u16 fw_ver_sub(struct crete_core_dev *dev)
|
||||
{
|
||||
struct crete_hw *hw = &dev->hw;
|
||||
|
||||
return readw(&hw->io_addr->cmd_interface_rev);
|
||||
}
|
||||
|
||||
static inline u16 fw_ver_rev(struct crete_core_dev *dev)
|
||||
{
|
||||
struct crete_hw *hw = &dev->hw;
|
||||
|
||||
return readw(&hw->io_addr->fw_revision);
|
||||
}
|
||||
|
||||
int crete_req_msixirq(struct crete_core_dev *core_dev);
|
||||
void crete_free_msixirq(struct crete_core_dev *core_dev, int irq);
|
||||
|
||||
static inline bool __crete_test_bit(const u64 features, unsigned int fbit)
|
||||
{
|
||||
/* Did you forget to fix assumptions on max features? */
|
||||
if (__builtin_constant_p(fbit))
|
||||
BUILD_BUG_ON(fbit >= 64);
|
||||
else
|
||||
WARN_ON_ONCE(fbit >= 64);
|
||||
|
||||
return features & BIT_ULL(fbit);
|
||||
}
|
||||
|
||||
static inline bool crete_has_feature(const struct crete_core_dev *cdev,
|
||||
enum crete_feature_type feature_type, unsigned int fbit)
|
||||
{
|
||||
if (feature_type == CRETE_FEATURE_NETDEV)
|
||||
return __crete_test_bit(cdev->netdev_features, fbit);
|
||||
else
|
||||
return __crete_test_bit(cdev->offload_features, fbit);
|
||||
}
|
||||
|
||||
/* NEED_ETH_HW_ADDR_SET
|
||||
*
|
||||
* eth_hw_addr_set was added by upstream commit
|
||||
* 48eab831ae8b ("net: create netdev->dev_addr assignment helpers")
|
||||
*
|
||||
* Using eth_hw_addr_set became required in 5.17, when the dev_addr field in
|
||||
* the netdev struct was constified. See 48eab831ae8b ("net: create
|
||||
* netdev->dev_addr assignment helpers")
|
||||
*/
|
||||
#ifdef NEED_ETH_HW_ADDR_SET
|
||||
static inline void eth_hw_addr_set(struct net_device *dev, const u8 *addr)
|
||||
{
|
||||
ether_addr_copy(dev->dev_addr, addr);
|
||||
}
|
||||
#endif /* NEED_ETH_HW_ADDR_SET */
|
||||
|
||||
int crete_cmd_init(struct crete_core_dev *cdev);
|
||||
int crete_event_init(struct crete_hw *hw);
|
||||
void crete_cmd_exit(struct crete_core_dev *cdev);
|
||||
void crete_event_exit(struct crete_hw *hw);
|
||||
int crete_adev_init(struct crete_core_dev *core_dev);
|
||||
void crete_adev_cleanup(struct crete_core_dev *core_dev);
|
||||
int crete_rescan_drivers_locked(struct crete_core_dev *core_dev);
|
||||
int crete_rescan_drivers(struct crete_core_dev *dev);
|
||||
void crete_dev_list_lock(void);
|
||||
void crete_dev_list_unlock(void);
|
||||
int crete_dev_list_trylock(void);
|
||||
void crete_sriov_disable(struct pci_dev *pdev);
|
||||
int crete_register_device(struct crete_core_dev *core_dev);
|
||||
void crete_unregister_device(struct crete_core_dev *core_dev);
|
||||
|
||||
void crete_detach_device(struct crete_core_dev *core_dev);
|
||||
int crete_attach_device(struct crete_core_dev *core_dev);
|
||||
int crete_change_mac_addr(struct net_device *netdev, void *p);
|
||||
void crete_set_rx_mode(struct net_device *dev);
|
||||
void crete_init_msix(struct crete_core_dev *core_dev);
|
||||
void crete_exit_irq(struct crete_core_dev *core_dev);
|
||||
extern struct dentry *crete_debugfs_root;
|
||||
void crete_register_debugfs(void);
|
||||
void crete_unregister_debugfs(void);
|
||||
struct dentry *crete_debugfs_get_dev_root(struct crete_core_dev *dev);
|
||||
extern const struct net_device_ops crete_netdev_ops;
|
||||
extern const struct ethtool_ops crete_ethtool_ops;
|
||||
#endif
|
@ -0,0 +1,378 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#include "crete.h"
|
||||
#include "crete_rdma_dev.h"
|
||||
#include "crete_devlink.h"
|
||||
static DEFINE_MUTEX(crete_intf_mutex);
|
||||
static DEFINE_IDA(crete_adev_ida);
|
||||
|
||||
|
||||
|
||||
|
||||
enum {
|
||||
CRETE_INTERFACE_PROTOCOL_ETH,
|
||||
CRETE_INTERFACE_PROTOCOL_ETH_REP,
|
||||
|
||||
CRETE_INTERFACE_PROTOCOL_IB,
|
||||
CRETE_INTERFACE_PROTOCOL_IB_REP,
|
||||
CRETE_INTERFACE_PROTOCOL_VNET,
|
||||
CRETE_INTERFACE_PROTOCOL_VNIC,
|
||||
CRETE_INTERFACE_PROTOCOL_MAX
|
||||
};
|
||||
|
||||
static const struct crete_adev_device {
|
||||
const char *suffix;
|
||||
bool (*is_supported)(struct crete_core_dev *core_dev);
|
||||
bool (*is_enabled)(struct crete_core_dev *core_dev);
|
||||
} crete_adev_devices[] = {
|
||||
[CRETE_INTERFACE_PROTOCOL_ETH] = { .suffix = "eth",
|
||||
.is_supported = &crete_eth_supported,
|
||||
.is_enabled = &crete_eth_enabled },
|
||||
[CRETE_INTERFACE_PROTOCOL_ETH_REP] = { .suffix = "eth-rep",
|
||||
.is_supported = &crete_eth_rep_supported,
|
||||
.is_enabled = &crete_eth_rep_enabled },
|
||||
/*
|
||||
* [CRETE_INTERFACE_PROTOCOL_IB] = { .suffix = "rdma",
|
||||
* .is_supported = &crete_rdma_supported,
|
||||
* .is_enabled = &crete_rdma_enabled },
|
||||
* [CRETE_INTERFACE_PROTOCOL_IB_REP] = { .suffix = "rdma-rep",
|
||||
* .is_supported = &crete_rdma_rep_supported,
|
||||
* .is_enabled = &crete_rdma_rep_enabled },
|
||||
*/
|
||||
[CRETE_INTERFACE_PROTOCOL_VNET] = { .suffix = "vnet",
|
||||
.is_supported = &crete_vnet_supported,
|
||||
.is_enabled = &crete_vnet_enabled },
|
||||
[CRETE_INTERFACE_PROTOCOL_VNIC] = { .suffix = "nic",
|
||||
.is_supported = &crete_nic_supported,
|
||||
.is_enabled = &crete_nic_enabled },
|
||||
};
|
||||
|
||||
int crete_adev_idx_alloc(void)
|
||||
{
|
||||
return ida_alloc(&crete_adev_ida, GFP_KERNEL);
|
||||
}
|
||||
|
||||
void crete_adev_idx_free(int idx)
|
||||
{
|
||||
ida_free(&crete_adev_ida, idx);
|
||||
}
|
||||
|
||||
|
||||
int crete_adev_init(struct crete_core_dev *core_dev)
|
||||
{
|
||||
struct crete_aux_dev **adev;
|
||||
|
||||
adev = kcalloc(ARRAY_SIZE(crete_adev_devices),
|
||||
sizeof(struct crete_aux_dev *), GFP_KERNEL | GFP_ATOMIC);
|
||||
if (!adev)
|
||||
return -ENOMEM;
|
||||
|
||||
core_dev->adev = adev;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void crete_adev_cleanup(struct crete_core_dev *core_dev)
|
||||
{
|
||||
struct crete_aux_dev **adev = core_dev->adev;
|
||||
|
||||
kfree(adev);
|
||||
}
|
||||
|
||||
static void crete_adev_release(struct device *dev)
|
||||
{
|
||||
struct crete_aux_dev *crete_adev =
|
||||
container_of(dev, struct crete_aux_dev, adev.dev);
|
||||
int idx = crete_adev->idx;
|
||||
struct crete_core_dev *core_dev = crete_adev->core_dev;
|
||||
|
||||
kfree(crete_adev);
|
||||
core_dev->adev[idx] = NULL;
|
||||
}
|
||||
|
||||
static struct crete_aux_dev *add_adev(struct crete_core_dev *core_dev,
|
||||
int idx)
|
||||
{
|
||||
const char *suffix = crete_adev_devices[idx].suffix;
|
||||
struct auxiliary_device *adev;
|
||||
struct crete_aux_dev *madev;
|
||||
int ret;
|
||||
|
||||
madev = kzalloc(sizeof(*madev), GFP_KERNEL);
|
||||
if (!madev)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
adev = &madev->adev;
|
||||
adev->id = core_dev->adev_idx;
|
||||
adev->name = suffix;
|
||||
adev->dev.parent = &core_dev->pdev->dev;
|
||||
adev->dev.release = crete_adev_release;
|
||||
madev->core_dev = core_dev;
|
||||
madev->idx = idx;
|
||||
|
||||
ret = auxiliary_device_init(adev);
|
||||
if (ret) {
|
||||
kfree(madev);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
ret = auxiliary_device_add(adev);
|
||||
if (ret) {
|
||||
auxiliary_device_uninit(adev);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
return madev;
|
||||
}
|
||||
|
||||
static void del_adev(struct auxiliary_device *adev)
|
||||
{
|
||||
auxiliary_device_delete(adev);
|
||||
auxiliary_device_uninit(adev);
|
||||
}
|
||||
|
||||
int crete_attach_device(struct crete_core_dev *core_dev)
|
||||
{
|
||||
struct crete_aux_dev **crete_adev = core_dev->adev;
|
||||
struct auxiliary_device *adev;
|
||||
struct auxiliary_driver *adrv;
|
||||
int ret = 0, i;
|
||||
|
||||
mutex_lock(&crete_intf_mutex);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(crete_adev_devices); i++) {
|
||||
if (!crete_adev[i]) {
|
||||
bool is_supported = false;
|
||||
|
||||
if (crete_adev_devices[i].is_enabled) {
|
||||
bool enabled;
|
||||
|
||||
enabled = crete_adev_devices[i].is_enabled(core_dev);
|
||||
if (!enabled)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (crete_adev_devices[i].is_supported)
|
||||
is_supported = crete_adev_devices[i].is_supported(core_dev);
|
||||
|
||||
if (!is_supported)
|
||||
continue;
|
||||
|
||||
crete_adev[i] = add_adev(core_dev, i);
|
||||
if (IS_ERR(crete_adev[i])) {
|
||||
ret = PTR_ERR(crete_adev[i]);
|
||||
crete_adev[i] = NULL;
|
||||
}
|
||||
} else {
|
||||
adev = &crete_adev[i]->adev;
|
||||
|
||||
if (!adev->dev.driver)
|
||||
continue;
|
||||
adrv = to_auxiliary_drv(adev->dev.driver);
|
||||
|
||||
if (adrv->resume)
|
||||
ret = adrv->resume(adev);
|
||||
}
|
||||
if (ret) {
|
||||
WARN_ONCE(1, "Device[%d] (%s) failed to load\n",
|
||||
i, crete_adev_devices[i].suffix);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&crete_intf_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void crete_detach_device(struct crete_core_dev *core_dev)
|
||||
{
|
||||
struct crete_aux_dev **crete_adev = core_dev->adev;
|
||||
struct auxiliary_device *adev;
|
||||
struct auxiliary_driver *adrv;
|
||||
pm_message_t pm = {};
|
||||
int i;
|
||||
|
||||
if (!crete_adev)
|
||||
pr_err("crete adev null\n");
|
||||
|
||||
mutex_lock(&crete_intf_mutex);
|
||||
for (i = ARRAY_SIZE(crete_adev_devices) - 1; i >= 0; i--) {
|
||||
if (!crete_adev[i])
|
||||
continue;
|
||||
|
||||
if (crete_adev_devices[i].is_enabled) {
|
||||
bool enabled;
|
||||
|
||||
enabled = crete_adev_devices[i].is_enabled(core_dev);
|
||||
if (!enabled)
|
||||
goto skip_suspend;
|
||||
}
|
||||
|
||||
adev = &crete_adev[i]->adev;
|
||||
/* Auxiliary driver was unbind manually through sysfs */
|
||||
if (!adev->dev.driver)
|
||||
goto skip_suspend;
|
||||
|
||||
adrv = to_auxiliary_drv(adev->dev.driver);
|
||||
|
||||
if (adrv->suspend) {
|
||||
adrv->suspend(adev, pm);
|
||||
continue;
|
||||
}
|
||||
|
||||
skip_suspend:
|
||||
del_adev(&crete_adev[i]->adev);
|
||||
crete_adev[i] = NULL;
|
||||
}
|
||||
|
||||
mutex_unlock(&crete_intf_mutex);
|
||||
}
|
||||
|
||||
int crete_register_device(struct crete_core_dev *core_dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&crete_intf_mutex);
|
||||
core_dev->flags &= ~CRETE_FLAG_DISABLE_ALL_ADEV;
|
||||
ret = crete_rescan_drivers_locked(core_dev);
|
||||
if (crete_have_rdma_cap(core_dev))
|
||||
ret |= jm_rescan_drivers_locked(&core_dev->rdma_coredev);
|
||||
mutex_unlock(&crete_intf_mutex);
|
||||
if (ret)
|
||||
crete_unregister_device(core_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void crete_unregister_device(struct crete_core_dev *core_dev)
|
||||
{
|
||||
mutex_lock(&crete_intf_mutex);
|
||||
core_dev->flags |= CRETE_FLAG_DISABLE_ALL_ADEV;
|
||||
if (crete_have_rdma_cap(core_dev))
|
||||
jm_rescan_drivers_locked(&core_dev->rdma_coredev);
|
||||
crete_rescan_drivers_locked(core_dev);
|
||||
mutex_unlock(&crete_intf_mutex);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int add_drivers(struct crete_core_dev *core_dev)
|
||||
{
|
||||
int i, ret = 0;
|
||||
struct crete_aux_dev **crete_adev = core_dev->adev;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(crete_adev_devices); i++) {
|
||||
bool is_supported = false;
|
||||
|
||||
if (crete_adev[i])
|
||||
continue;
|
||||
|
||||
if (crete_adev_devices[i].is_supported)
|
||||
is_supported = crete_adev_devices[i].is_supported(core_dev);
|
||||
|
||||
if (!is_supported)
|
||||
continue;
|
||||
|
||||
crete_adev[i] = add_adev(core_dev, i);
|
||||
if (IS_ERR(crete_adev[i])) {
|
||||
WARN_ONCE(1, "Device[%d] (%s) failed to load\n",
|
||||
i, crete_adev_devices[i].suffix);
|
||||
/* We continue to rescan drivers and leave to the caller
|
||||
* to make decision if to release everything or continue.
|
||||
*/
|
||||
ret = PTR_ERR(crete_adev[i]);
|
||||
crete_adev[i] = NULL;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void delete_drivers(struct crete_core_dev *core_dev)
|
||||
{
|
||||
struct crete_aux_dev **crete_adev = core_dev->adev;
|
||||
bool delete_all;
|
||||
int i;
|
||||
|
||||
delete_all = core_dev->flags & CRETE_FLAG_DISABLE_ALL_ADEV;
|
||||
for (i = ARRAY_SIZE(crete_adev_devices) - 1; i >= 0; i--) {
|
||||
bool is_supported = false;
|
||||
|
||||
if (!crete_adev[i])
|
||||
continue;
|
||||
|
||||
if (crete_adev_devices[i].is_enabled) {
|
||||
bool enabled;
|
||||
|
||||
enabled = crete_adev_devices[i].is_enabled(core_dev);
|
||||
if (!enabled)
|
||||
goto del_adev;
|
||||
}
|
||||
|
||||
if (crete_adev_devices[i].is_supported && !delete_all)
|
||||
is_supported = crete_adev_devices[i].is_supported(core_dev);
|
||||
|
||||
if (is_supported)
|
||||
continue;
|
||||
|
||||
del_adev:
|
||||
del_adev(&crete_adev[i]->adev);
|
||||
crete_adev[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int crete_rescan_drivers_locked(struct crete_core_dev *core_dev)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
delete_drivers(core_dev);
|
||||
if (core_dev->flags & CRETE_FLAG_DISABLE_ALL_ADEV)
|
||||
return 0;
|
||||
|
||||
err = add_drivers(core_dev);
|
||||
return err;
|
||||
}
|
||||
void crete_dev_list_lock(void)
|
||||
{
|
||||
mutex_lock(&crete_intf_mutex);
|
||||
}
|
||||
void crete_dev_list_unlock(void)
|
||||
{
|
||||
mutex_unlock(&crete_intf_mutex);
|
||||
}
|
||||
|
||||
int crete_dev_list_trylock(void)
|
||||
{
|
||||
return mutex_trylock(&crete_intf_mutex);
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,367 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _CRETE_CMD_H
|
||||
#define _CRETE_CMD_H
|
||||
|
||||
#include "crete.h"
|
||||
#include <linux/types.h>
|
||||
#include <uapi/linux/stddef.h>
|
||||
|
||||
extern uint crete_cmd_debug_sw;
|
||||
|
||||
#define CRETE_CMD_INLINE_LEN 36
|
||||
#define CRETE_CMD_TRY_NUM 60
|
||||
#define CRETE_TO_CMD_MS 60000
|
||||
#define OWNER_MASK 0x1
|
||||
#define CRETE_GET_CMD_BD_LEN(len) \
|
||||
(((len) > CRETE_CMD_DATA_BLOCK_SIZE) ? \
|
||||
DIV_ROUND_UP(CRETE_CMD_DATA_BLOCK_SIZE + sizeof(struct crete_cmd_prot_block), 4) : \
|
||||
DIV_ROUND_UP((len) + sizeof(struct crete_cmd_prot_block), 4))
|
||||
|
||||
#define CRETE_COMMAND_STR_CASE(__cmd) case CRETE_CMD_ ## __cmd: return #__cmd
|
||||
|
||||
#define crete_cmd_dbg(__dev, format, ...) \
|
||||
dev_dbg((__dev)->device, "%s:%d:(pid %d): " format, \
|
||||
__func__, __LINE__, current->pid, \
|
||||
##__VA_ARGS__)
|
||||
|
||||
#define crete_cmd_dbg_mask(__dev, mask, format, ...) \
|
||||
do { \
|
||||
if ((mask) & crete_cmd_debug_sw) \
|
||||
crete_cmd_dbg(__dev, format, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
/* helper macros */
|
||||
#define __crete_nullp(typ) ((struct crete_cmd_##typ##_bits *)0)
|
||||
#define __crete_bit_sz(typ, fld) sizeof(__crete_nullp(typ)->fld)
|
||||
#define __crete_bit_off(typ, fld) (offsetof(struct crete_cmd_##typ##_bits, fld))
|
||||
#define __crete_16_off(typ, fld) (__crete_bit_off(typ, fld) / 16)
|
||||
#define __crete_dw_off(typ, fld) (__crete_bit_off(typ, fld) / 32)
|
||||
#define __crete_64_off(typ, fld) (__crete_bit_off(typ, fld) / 64)
|
||||
#define __crete_16_bit_off(typ, fld) (__crete_bit_off(typ, fld) & 0xf)
|
||||
#define __crete_dw_bit_off(typ, fld) (__crete_bit_off(typ, fld) & 0x1f)
|
||||
#define __crete_mask(typ, fld) ((u32)((1ull << __crete_bit_sz(typ, fld)) - 1))
|
||||
#define __crete_dw_mask(typ, fld) (__crete_mask(typ, fld) << __crete_dw_bit_off(typ, fld))
|
||||
#define __crete_mask16(typ, fld) ((u16)((1ull << __crete_bit_sz(typ, fld)) - 1))
|
||||
#define __crete_16_mask(typ, fld) (__crete_mask16(typ, fld) << __crete_16_bit_off(typ, fld))
|
||||
#define __crete_st_sz_bits(typ) sizeof(struct crete_cmd_##typ##_bits)
|
||||
|
||||
#define CRETE_FLD_SZ_BYTES(typ, fld) (__crete_bit_sz(typ, fld) / 8)
|
||||
#define CRETE_ST_SZ_BYTES(typ) (sizeof(struct crete_cmd_##typ##_bits) / 8)
|
||||
#define CRETE_ST_SZ_DW(typ) (sizeof(struct crete_cmd_##typ##_bits) / 32)
|
||||
#define CRETE_ST_SZ_QW(typ) (sizeof(struct crete_cmd_##typ##_bits) / 64)
|
||||
#define CRETE_UN_SZ_BYTES(typ) (sizeof(union crete_cmd_##typ##_bits) / 8)
|
||||
#define CRETE_UN_SZ_DW(typ) (sizeof(union crete_cmd_##typ##_bits) / 32)
|
||||
#define CRETE_BYTE_OFF(typ, fld) (__crete_bit_off(typ, fld) / 8)
|
||||
#define CRETE_ADDR_OF(typ, p, fld) ((void *)((uint8_t *)(p) + CRETE_BYTE_OFF(typ, fld)))
|
||||
|
||||
/* insert a value to a struct */
|
||||
#define CRETE_SET(typ, p, fld, v) do { \
|
||||
u32 _v = v; \
|
||||
BUILD_BUG_ON(__crete_st_sz_bits(typ) % 32); \
|
||||
*((__le32 *)(p) + __crete_dw_off(typ, fld)) = \
|
||||
cpu_to_le32((le32_to_cpu(*((__le32 *)(p) + __crete_dw_off(typ, fld))) & \
|
||||
(~__crete_dw_mask(typ, fld))) | (((_v) & __crete_mask(typ, fld)) \
|
||||
<< __crete_dw_bit_off(typ, fld))); \
|
||||
} while (0)
|
||||
|
||||
#define CRETE_ARRAY_SET(typ, p, fld, idx, v) do { \
|
||||
BUILD_BUG_ON(__crete_bit_off(typ, fld) % 32); \
|
||||
CRETE_SET(typ, p, fld[idx], v); \
|
||||
} while (0)
|
||||
|
||||
#define CRETE_SET_TO_ONES(typ, p, fld) do { \
|
||||
BUILD_BUG_ON(__crete_st_sz_bits(typ) % 32); \
|
||||
*((__le32 *)(p) + __crete_dw_off(typ, fld)) = \
|
||||
cpu_to_le32((le32_to_cpu(*((__le32 *)(p) + __crete_dw_off(typ, fld))) & \
|
||||
(~__crete_dw_mask(typ, fld))) | ((__crete_mask(typ, fld)) \
|
||||
<< __crete_dw_bit_off(typ, fld))); \
|
||||
} while (0)
|
||||
|
||||
#define CRETE_GET(typ, p, fld) ((le32_to_cpu(*((__le32 *)(p) +\
|
||||
__crete_dw_off(typ, fld))) >> __crete_dw_bit_off(typ, fld)) & \
|
||||
__crete_mask(typ, fld))
|
||||
|
||||
#define CRETE_GET_PR(typ, p, fld) ({ \
|
||||
u32 ___t = CRETE_GET(typ, p, fld); \
|
||||
pr_debug(#fld " = 0x%x\n", ___t); \
|
||||
___t; \
|
||||
})
|
||||
|
||||
#define __CRETE_SET64(typ, p, fld, v) do { \
|
||||
BUILD_BUG_ON(__crete_bit_sz(typ, fld) != 64); \
|
||||
*((__le64 *)(p) + __crete_64_off(typ, fld)) = cpu_to_le64(v); \
|
||||
} while (0)
|
||||
|
||||
#define CRETE_SET64(typ, p, fld, v) do { \
|
||||
BUILD_BUG_ON(__crete_bit_off(typ, fld) % 64); \
|
||||
__CRETE_SET64(typ, p, fld, v); \
|
||||
} while (0)
|
||||
|
||||
#define CRETE_ARRAY_SET64(typ, p, fld, idx, v) do { \
|
||||
BUILD_BUG_ON(__crete_bit_off(typ, fld) % 64); \
|
||||
__CRETE_SET64(typ, p, fld[idx], v); \
|
||||
} while (0)
|
||||
|
||||
#define CRETE_GET64(typ, p, fld) le64_to_cpu(*((__le64 *)(p) + __crete_64_off(typ, fld)))
|
||||
|
||||
#define CRETE_GET64_PR(typ, p, fld) ({ \
|
||||
u64 ___t = CRETE_GET64(typ, p, fld); \
|
||||
pr_debug(#fld " = 0x%llx\n", ___t); \
|
||||
___t; \
|
||||
})
|
||||
|
||||
#define CRETE_GET16(typ, p, fld) ((le16_to_cpu(*((__le16 *)(p) +\
|
||||
__crete_16_off(typ, fld))) >> __crete_16_bit_off(typ, fld)) & \
|
||||
__crete_mask16(typ, fld))
|
||||
|
||||
#define CRETE_SET16(typ, p, fld, v) do { \
|
||||
u16 _v = v; \
|
||||
BUILD_BUG_ON(__crete_st_sz_bits(typ) % 16); \
|
||||
*((__le16 *)(p) + __crete_16_off(typ, fld)) = \
|
||||
cpu_to_le16((le16_to_cpu(*((__le16 *)(p) + __crete_16_off(typ, fld))) & \
|
||||
(~__crete_16_mask(typ, fld))) | (((_v) & __crete_mask16(typ, fld)) \
|
||||
<< __crete_16_bit_off(typ, fld))); \
|
||||
} while (0)
|
||||
|
||||
|
||||
enum {
|
||||
CMD_MODE_POLLING,
|
||||
CMD_MODE_EVENTS
|
||||
};
|
||||
|
||||
enum {
|
||||
CMD_OWNER_SW = 0x0,
|
||||
CMD_OWNER_HW = 0x1,
|
||||
};
|
||||
|
||||
/* cmd delivery status */
|
||||
enum crete_cmd_status {
|
||||
CRETE_CMD_DELIVERY_STAT_OK = 0x0,
|
||||
CRETE_CMD_DELIVERY_STAT_SIGNAT_ERR = 0x1,
|
||||
CRETE_CMD_DELIVERY_STAT_CID_ERR = 0x2,
|
||||
CRETE_CMD_DELIVERY_STAT_DATA_FORMAT_ERR = 0x3,
|
||||
CRETE_CMD_DELIVERY_STAT_OUT_INSUFFICIENT_ERR = 0x4,
|
||||
CRETE_CMD_DELIVERY_STAT_OWNER_ERR = 0x5,
|
||||
};
|
||||
|
||||
/* return cmd status */
|
||||
enum return_cmd_status {
|
||||
SUCCESS,
|
||||
INTERNAL_ERR,
|
||||
BAD_ID,
|
||||
BAD_OP,
|
||||
BAD_PARAM,
|
||||
BAD_STATE,
|
||||
BAD_RESOURCE,
|
||||
};
|
||||
|
||||
|
||||
enum {
|
||||
CRETE_CMD_ENT_STATE_PENDING_COMP,
|
||||
};
|
||||
|
||||
enum {
|
||||
CRETE_TRIGGERED_CMD_COMP = (u64)1 << 32,
|
||||
};
|
||||
|
||||
/* cmd id */
|
||||
enum crete_gener_cmd_id {
|
||||
CRETE_CMD_GET_STATUS = 0x100,
|
||||
CRETE_CMD_SET_STATUS,
|
||||
CRETE_CMD_GET_FEAT,
|
||||
CRETE_CMD_SET_FEAT,
|
||||
CRETE_CMD_GET_DEV_TYPE,
|
||||
CRETE_CMD_SET_DEV_TYPE,
|
||||
CRETE_CMD_RESET_DEV,
|
||||
CRETE_CMD_STOP_DEV,
|
||||
CRETE_CMD_RESTORE_DEV,
|
||||
CRETE_CMD_GET_DEV_ATTR,
|
||||
CRETE_CMD_SET_QP_NUM = 0x10a,
|
||||
CRETE_CMD_GET_SFI = 0x110,
|
||||
CRETE_CMD_GEN_MAX,
|
||||
};
|
||||
|
||||
/* qp group */
|
||||
enum crete_qp_cmd_id {
|
||||
CRETE_CMD_GET_QP_CAP = 0x300,
|
||||
CRETE_CMD_CREATE_QP,
|
||||
CRETE_CMD_DESTORY_QP,
|
||||
CRETE_CMD_CREATE_QUEUE,
|
||||
CRETE_CMD_DESTROY_QUEUE = 0x304,
|
||||
CRETE_CMD_ENABLE_QUEUE = 0x305,
|
||||
CRETE_CMD_DISABLE_QUEUE = 0x306,
|
||||
CRETE_CMD_ENABLE_RXEN,
|
||||
CRETE_CMD_DISABLE_RXEN,
|
||||
CRETE_CMD_RESET_QUEUE = 0x309,
|
||||
CRETE_CMD_GET_Q_STATE,
|
||||
CRETE_CMD_QP_MAX,
|
||||
};
|
||||
|
||||
|
||||
enum crete_vport_cmd_id {
|
||||
CRETE_CMD_SET_VPORT_RX_MODE = 0x500,
|
||||
CRETE_CMD_SET_ESWITCH_MODE = 0x501,
|
||||
CRETE_CMD_VPORT_ATTR_GET = 0x502,
|
||||
|
||||
CRETE_CMD_SET_VPORT_LINK_STATE = 0x505,
|
||||
CRETE_CMD_SET_MTU = 0x506,
|
||||
|
||||
CRETE_CMD_SET_TRUST = 0x508,
|
||||
CRETE_CMD_GET_VPORT_PKT_STAT = 0x509,
|
||||
|
||||
CRETE_CMD_GET_VPORT_LINK_STATE,
|
||||
CRETE_CMD_GET_VORT_RX_MODE,
|
||||
CRETE_CMD_SET_TCP_LRO,
|
||||
CRETE_CMD_GET_TCP_LRO,
|
||||
CRETE_CMD_SET_RX_RSS,
|
||||
CRETE_CMD_GET_RX_RSS,
|
||||
CRETE_CMD_SET_RX_TIMESTAMP,
|
||||
CRETE_CMD_GET_RX_TIMESTAMP,
|
||||
CRETE_CMD_GET_TRUST,
|
||||
CRETE_CMD_SET_UC_MAC,
|
||||
CRETE_CMD_SET_VF_SHAPER = 0x551,
|
||||
CRETE_CMD_VPORT_MAX,
|
||||
};
|
||||
|
||||
/*
|
||||
enum crete_vport_cmd_id {
|
||||
CRETE_CMD_SET_VPORT_RX_MODE = 0x500,
|
||||
CRETE_CMD_GET_VORT_RX_MODE,
|
||||
CRETE_CMD_VPORT_ATTR_GET,
|
||||
// CRETE_CMD_SET_VPORT_LINK_STATE,
|
||||
CRETE_CMD_GET_VPORT_LINK_STATE,
|
||||
CRETE_CMD_SET_TCP_LRO,
|
||||
CRETE_CMD_GET_TCP_LRO,
|
||||
CRETE_CMD_SET_RX_RSS,
|
||||
CRETE_CMD_GET_RX_RSS,
|
||||
CRETE_CMD_SET_RX_TIMESTAMP,
|
||||
CRETE_CMD_GET_RX_TIMESTAMP,
|
||||
CRETE_CMD_SET_TRUST,
|
||||
CRETE_CMD_GET_TRUST,
|
||||
CRETE_CMD_SET_UC_MAC = 0x50c,
|
||||
CRETE_CMD_SET_VF_SHAPER = 0x50d,
|
||||
CRETE_CMD_SET_VPORT_LINK_STATE,
|
||||
CRETE_CMD_VPORT_MAX,
|
||||
};
|
||||
|
||||
*/
|
||||
|
||||
/* port group */
|
||||
enum crete_port_cmd_id {
|
||||
CRETE_CMD_SET_PORT_TRUST_STATUS = 0x801,
|
||||
CRETE_CMD_SET_PCP_MAP_TC,
|
||||
CRETE_CMD_SET_DSCP_MAP_TC,
|
||||
CRETE_CMD_SET_FC_ENABLE,
|
||||
CRETE_CMD_SET_FC_TIMEOUT,
|
||||
CRETE_CMD_SET_PFC_ENABLE,
|
||||
CRETE_CMD_SET_ETS,
|
||||
CRETE_CMD_GET_PORT_NUM = 0x808,
|
||||
CRETE_CMD_GET_PORT_LINK_STATUS,
|
||||
CRETE_CMD_GET_REPORT_PORT_LINK_STATUS,
|
||||
CRETE_CMD_GET_PORT_SPEED_DUPLEX_MODE,
|
||||
CRETE_CMD_SET_PORT_SPEED_DUPLEX_MODE,
|
||||
CRETE_CMD_GET_PORT_FEC_MODE,
|
||||
CRETE_CMD_SET_PORT_FEC_MODE,
|
||||
CRETE_CMD_PORT_MAX,
|
||||
};
|
||||
|
||||
/* netdev group */
|
||||
enum crete_netdev_cmd_id {
|
||||
CRETE_CMD_SET_SOP_PADDING = 0x400,
|
||||
CRETE_CMD_GET_SOP_PADDING,
|
||||
CRETE_CMD_SET_AUTO_SUPPRESS,
|
||||
CRETE_CMD_GET_AUTO_SUPPRESS,
|
||||
CRETE_CMD_SET_MODERATION_TEMP,
|
||||
CRETE_CMD_GET_MODERATION_TEMP,
|
||||
CRETE_CMD_SET_INT_MODERATION,
|
||||
CRETE_CMD_GET_INT_MODERATION,
|
||||
CRETE_CMD_SET_TX_INORDER,
|
||||
CRETE_CMD_GET_TX_INORDER,
|
||||
CRETE_CMD_SET_CQE_AGGREGATION_TEMP,
|
||||
CRETE_CMD_GET_CQE_AGGREGATION_TEMP,
|
||||
CRETE_CMD_SET_CQE_AGGREGATION,
|
||||
CRETE_CMD_GET_CQE_AGGREGATION,
|
||||
CRETE_CMD_SET_RX_MERGE,
|
||||
CRETE_CMD_GET_RX_MERGE,
|
||||
CRETE_CMD_NEDEV_MAX,
|
||||
};
|
||||
|
||||
enum crete_lag_cmd_id {
|
||||
CRETE_CMD_GET_LAG_CAP = 0x0503,
|
||||
CRETE_CMD_LAG_CONFIG = 0x0504,
|
||||
CRETE_CMD_ENABLE_LAG = 0x050c,
|
||||
};
|
||||
|
||||
/* migration cmd*/
|
||||
enum crete_lm_cmd_id {
|
||||
CRETE_CMD_SET_VQ_MIG_STATE = 0x30c,
|
||||
CRETE_CMD_GET_VQ_MIG_STATE = 0x30d,
|
||||
CRETE_CMD_GET_VQ_MIG_STATE_BATCH = 0x30e,
|
||||
CRETE_CMD_SET_MIG_LOG_STATE = 0x112,
|
||||
CRETE_CMD_SET_MIG_LOG_BASE = 0x113,
|
||||
};
|
||||
|
||||
/* firmware */
|
||||
enum crete_firmware_cmd_id {
|
||||
CRETE_CMD_FWU_LOCK = 0x201,
|
||||
CRETE_CMD_FWU_UNLOCK,
|
||||
CRETE_CMD_FWU_PKEY,
|
||||
CRETE_CMD_FWU_VER,
|
||||
CRETE_CMD_FWU_XFER,
|
||||
CRETE_CMD_FWU_END,
|
||||
};
|
||||
|
||||
/*set mtu*/
|
||||
enum crete_set_mtu_op {
|
||||
CRETE_SET_MTU_MACPORT = 1,
|
||||
CRETE_SET_MTU_VPORT = 2,
|
||||
};
|
||||
|
||||
#define MAC_MTU(v) ((v) + ETH_HLEN)
|
||||
|
||||
/*get vport pkt statistics*/
|
||||
enum crete_get_vport_statistics_op {
|
||||
CRETE_GET_PKT_STATIS_VPORT = 0,
|
||||
CRETE_GET_PKT_STATIS_MAC = 1,
|
||||
CRETE_GET_PKT_STATIS_LAG = 2,
|
||||
};
|
||||
|
||||
enum crete_tmplate_cmd_id {
|
||||
CRETE_CMD_GET_VF_MAC = 0x8101,
|
||||
};
|
||||
|
||||
int crete_cmd_exec_polling(struct crete_core_dev *dev, void *in, int in_size,
|
||||
void *out, int out_size);
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,22 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include "crete.h"
|
||||
|
||||
struct dentry *crete_debugfs_root;
|
||||
EXPORT_SYMBOL(crete_debugfs_root);
|
||||
|
||||
void crete_register_debugfs(void)
|
||||
{
|
||||
crete_debugfs_root = debugfs_create_dir("crete", NULL);
|
||||
}
|
||||
|
||||
void crete_unregister_debugfs(void)
|
||||
{
|
||||
debugfs_remove(crete_debugfs_root);
|
||||
}
|
||||
|
||||
struct dentry *crete_debugfs_get_dev_root(struct crete_core_dev *dev)
|
||||
{
|
||||
return dev->dbg.dbg_root;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,138 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __CRETE_DCBX_H__
|
||||
#define __CRETE_DCBX_H__
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/if_link.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/xarray.h>
|
||||
#include <net/devlink.h>
|
||||
|
||||
|
||||
#define CRETE_SUPPORTED_DSCP 64
|
||||
#define CRETE_SUPPORTED_PCP 8
|
||||
|
||||
#define CRETE_CMD_DSCP_BIT_WIDTH 0x8
|
||||
#define CRETE_CMD_DSCP_TC_MASK 0xF
|
||||
#define CRETE_CMD_DSCP_EN_SHIFT 0x7
|
||||
#define CRETE_CMD_QDSCP_NUM 16
|
||||
#define CRETE_CMD_QSCP_NUM_PERQ 4
|
||||
#define CRETE_DEFAULT_CABLE_LEN 7 /* 7 meters */
|
||||
|
||||
#define CRETE_1GB (1000000)
|
||||
#define CRETE_100MB (100000)
|
||||
|
||||
enum crete_dcbx_oper_mode {
|
||||
CRETE_DCBX_PARAM_VER_OPER_HOST = 0x0,
|
||||
CRETE_DCBX_PARAM_VER_OPER_AUTO = 0x3,
|
||||
};
|
||||
|
||||
enum {
|
||||
INIT,
|
||||
DELETE,
|
||||
};
|
||||
|
||||
struct crete_cee_config {
|
||||
/* bw pct for priority group */
|
||||
u8 pg_bw_pct[CEE_DCBX_MAX_PGS];
|
||||
u8 prio_to_pg_map[CEE_DCBX_MAX_PRIO];
|
||||
bool pfc_setting[CEE_DCBX_MAX_PRIO];
|
||||
bool pfc_enable;
|
||||
};
|
||||
|
||||
struct crete_dcbx_dp {
|
||||
u8 dscp2prio[CRETE_SUPPORTED_DSCP];
|
||||
u8 trust_state;
|
||||
};
|
||||
|
||||
|
||||
struct crete_dcbx {
|
||||
enum crete_dcbx_oper_mode mode;
|
||||
struct crete_cee_config cee_cfg; /* pending configuration */
|
||||
u8 dscp_app_cnt;
|
||||
|
||||
/* The only setting that cannot be read from FW */
|
||||
u8 tc_tsa[IEEE_8021QAZ_MAX_TCS];
|
||||
u8 cap;
|
||||
|
||||
/* Buffer configuration */
|
||||
bool manual_buffer;
|
||||
u32 cable_len;
|
||||
u32 xoff;
|
||||
u16 port_buff_cell_sz;
|
||||
};
|
||||
|
||||
enum crete_port_trust_state {
|
||||
CRETE_PORT_TRUST_PCP = 1,
|
||||
CRETE_PORT_TRUST_DSCP = 2,
|
||||
};
|
||||
|
||||
|
||||
enum {
|
||||
CRETE_DISABLE_MAXRATE = 0,
|
||||
CRETE_KBPS_UNIT = 1,
|
||||
CRETE_MBPS_UNIT = 2,
|
||||
CRETE_GBPS_UNIT = 3,
|
||||
CRETE_PPS_UNIT = 4,
|
||||
CRETE_KPPS_UNIT = 5,
|
||||
CRETE_MPPS_UNIT = 6,
|
||||
};
|
||||
|
||||
struct tc_configuration {
|
||||
u8 weight;
|
||||
u8 unit;
|
||||
u8 pg_id;
|
||||
u32 maxrate;
|
||||
};
|
||||
|
||||
struct dscp_configuration {
|
||||
u8 tc : 4;
|
||||
u8 en : 1;
|
||||
};
|
||||
|
||||
struct pcp_configuration {
|
||||
u8 tc : 3;
|
||||
u8 en : 1;
|
||||
};
|
||||
|
||||
struct crete_priv;
|
||||
void crete_dcbnl_build_netdev(struct net_device *netdev);
|
||||
void crete_dcbnl_initialize(struct crete_priv *priv);
|
||||
void crete_dcbnl_init_app(struct crete_priv *priv);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
@ -0,0 +1,102 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#include "crete.h"
|
||||
#include "crete_cmd_if.h"
|
||||
|
||||
static int statistics_show(struct seq_file *file, void *priv)
|
||||
{
|
||||
struct crete_core_dev *core_dev = file->private;
|
||||
struct crete_debugfs_statistics *debugfs_statis = core_dev->debugfs_statis;
|
||||
struct crete_port_statistics port_statistics;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&debugfs_statis->statis_mutex);
|
||||
|
||||
ret = crete_get_port_statistics(core_dev, &port_statistics);
|
||||
if(ret){
|
||||
mutex_unlock(&debugfs_statis->statis_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
debugfs_statis->rx_bytes += port_statistics.rx_bytes;
|
||||
debugfs_statis->rx_pkts += port_statistics.rx_pkts;
|
||||
debugfs_statis->tx_bytes += port_statistics.tx_bytes;
|
||||
debugfs_statis->tx_pkts += port_statistics.tx_pkts;
|
||||
|
||||
seq_printf(file, "rx bytes : 0x%llx\n", debugfs_statis->rx_bytes);
|
||||
seq_printf(file, "rx pkts : 0x%llx\n", debugfs_statis->rx_pkts);
|
||||
seq_printf(file, "tx bytes : 0x%llx\n", debugfs_statis->tx_bytes);
|
||||
seq_printf(file, "tx pkts : 0x%llx\n", debugfs_statis->tx_pkts);
|
||||
|
||||
mutex_unlock(&debugfs_statis->statis_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_SHOW_ATTRIBUTE(statistics);
|
||||
|
||||
int crete_register_debugfs_statistics(struct crete_core_dev *dev)
|
||||
{
|
||||
struct crete_debugfs_statistics *debugfs_statis = NULL;
|
||||
struct dentry *debugfs = NULL;
|
||||
|
||||
debugfs_statis = kzalloc(sizeof(*debugfs_statis), GFP_KERNEL);
|
||||
if(!debugfs_statis){
|
||||
dev_err(dev->device, "failed to alloc debugfs statistics\n");
|
||||
return -1;
|
||||
}
|
||||
mutex_init(&debugfs_statis->statis_mutex);
|
||||
dev->debugfs_statis = debugfs_statis;
|
||||
|
||||
debugfs = debugfs_create_file("statistics", 0444, crete_debugfs_get_dev_root(dev), dev, &statistics_fops);
|
||||
if(!debugfs){
|
||||
dev_err(dev->device, "failed to create debugfs file statistics\n");
|
||||
return -1;
|
||||
}
|
||||
dev->dbg.statistics_debugfs = debugfs;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crete_unregister_debugfs_statistics(struct crete_core_dev *dev)
|
||||
{
|
||||
if(dev->dbg.statistics_debugfs){
|
||||
debugfs_remove_recursive(dev->dbg.statistics_debugfs);
|
||||
}
|
||||
|
||||
if(dev->debugfs_statis){
|
||||
kfree(dev->debugfs_statis);
|
||||
dev->debugfs_statis = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#include <linux/mutex.h>
|
||||
|
||||
struct crete_debugfs_statistics {
|
||||
|
||||
struct mutex statis_mutex;
|
||||
|
||||
uint64_t tx_pkts;
|
||||
uint64_t tx_bytes;
|
||||
|
||||
uint64_t rx_pkts;
|
||||
uint64_t rx_bytes;
|
||||
};
|
||||
|
||||
int crete_register_debugfs_statistics(struct crete_core_dev *dev);
|
||||
int crete_unregister_debugfs_statistics(struct crete_core_dev *dev);
|
||||
|
@ -0,0 +1,542 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#include <net/devlink.h>
|
||||
#include "crete.h"
|
||||
#include "crete_eswitch.h"
|
||||
#include "crete_fw_update.h"
|
||||
|
||||
struct crete_eswitch *crete_devlink_eswitch_get(struct devlink *devlink)
|
||||
{
|
||||
struct crete_core_dev *dev = devlink_priv(devlink);
|
||||
|
||||
return dev->eswitch;
|
||||
}
|
||||
|
||||
static int esw_mode_from_devlink(u16 mode, u16 *crete_mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case DEVLINK_ESWITCH_MODE_LEGACY:
|
||||
*crete_mode = CRETE_ESWITCH_LEGACY;
|
||||
break;
|
||||
case DEVLINK_ESWITCH_MODE_SWITCHDEV:
|
||||
*crete_mode = CRETE_ESWITCH_OFFLOADS;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int esw_mode_to_devlink(u16 crete_mode, u16 *mode)
|
||||
{
|
||||
switch (crete_mode) {
|
||||
case CRETE_ESWITCH_LEGACY:
|
||||
*mode = DEVLINK_ESWITCH_MODE_LEGACY;
|
||||
break;
|
||||
case CRETE_ESWITCH_OFFLOADS:
|
||||
*mode = DEVLINK_ESWITCH_MODE_SWITCHDEV;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crete_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
u16 cur_crete_mode, crete_mode = 0;
|
||||
struct crete_eswitch *esw;
|
||||
int err = 0;
|
||||
|
||||
esw = crete_devlink_eswitch_get(devlink);
|
||||
if (IS_ERR(esw))
|
||||
return PTR_ERR(esw);
|
||||
|
||||
if (esw_mode_from_devlink(mode, &crete_mode))
|
||||
return -EINVAL;
|
||||
|
||||
err = crete_esw_try_lock(esw);
|
||||
if (err < 0) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Can't change mode, E-Switch is busy");
|
||||
goto eswitch_busy;
|
||||
}
|
||||
cur_crete_mode = err;
|
||||
err = 0;
|
||||
|
||||
if (cur_crete_mode == crete_mode)
|
||||
goto unlock;
|
||||
/* cmd queue notify firmware */
|
||||
crete_eswitch_disable_locked(esw);
|
||||
if (mode == DEVLINK_ESWITCH_MODE_SWITCHDEV) {
|
||||
err = esw_offloads_start(esw, extack);
|
||||
crete_rescan_drivers_locked(esw->dev);
|
||||
} else if (mode == DEVLINK_ESWITCH_MODE_LEGACY) {
|
||||
crete_rescan_drivers_locked(esw->dev);
|
||||
err = esw_offloads_stop(esw, extack);
|
||||
//crete_rescan_drivers_locked(esw->dev);
|
||||
} else {
|
||||
err = -EINVAL;
|
||||
}
|
||||
|
||||
unlock:
|
||||
crete_esw_unlock(esw);
|
||||
eswitch_busy:
|
||||
return err;
|
||||
}
|
||||
|
||||
int crete_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode)
|
||||
{
|
||||
struct crete_eswitch *esw;
|
||||
int err;
|
||||
|
||||
esw = crete_devlink_eswitch_get(devlink);
|
||||
if (IS_ERR(esw))
|
||||
return PTR_ERR(esw);
|
||||
|
||||
down_read(&esw->mode_lock);
|
||||
err = esw_mode_to_devlink(esw->mode, mode);
|
||||
up_read(&esw->mode_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int crete_devlink_flash_update(struct devlink *devlink,
|
||||
struct devlink_flash_update_params *params,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct crete_core_dev *cdev = devlink_priv(devlink);
|
||||
#ifndef CONFIG_DEVLINK_CARRYOUT_OPTIMIZE
|
||||
const struct firmware *fw;
|
||||
int err;
|
||||
|
||||
err = request_firmware_direct(&fw, params->file_name, cdev->device);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = crete_firmware_flash(cdev, fw, extack, CRETE_FWU_DEVLINK);
|
||||
release_firmware(fw);
|
||||
#else
|
||||
return crete_firmware_flash(cdev, params->fw, extack, CRETE_FWU_DEVLINK);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 crete_fw_ver_major(u32 version)
|
||||
{
|
||||
return (version >> 24) & 0xff;
|
||||
}
|
||||
|
||||
static u8 crete_fw_ver_minor(u32 version)
|
||||
{
|
||||
return (version >> 16) & 0xff;
|
||||
}
|
||||
|
||||
static u16 crete_fw_ver_subminor(u32 version)
|
||||
{
|
||||
return version & 0xffff;
|
||||
}
|
||||
|
||||
#define DEVLINK_FW_STRING_LEN 32
|
||||
int crete_fw_version_query(struct crete_core_dev *dev,
|
||||
u32 *running_ver, u32 *pending_ver)
|
||||
{
|
||||
dev_warn(&dev->pdev->dev, "%s devlink info get fw version stub\n", __func__);
|
||||
*running_ver = 0x20231025;
|
||||
*pending_ver = 0x20231024;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
crete_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct crete_core_dev *dev = devlink_priv(devlink);
|
||||
char version_str[DEVLINK_FW_STRING_LEN];
|
||||
u32 running_fw, stored_fw;
|
||||
int err;
|
||||
char *psid_stub = "crete_stub_psid";
|
||||
|
||||
err = devlink_info_version_fixed_put(req, "fw.psid", psid_stub);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = crete_fw_version_query(dev, &running_fw, &stored_fw);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
snprintf(version_str, sizeof(version_str), "%d.%d.%04d",
|
||||
crete_fw_ver_major(running_fw), crete_fw_ver_minor(running_fw),
|
||||
crete_fw_ver_subminor(running_fw));
|
||||
err = devlink_info_version_running_put(req, "fw.version", version_str);
|
||||
if (err)
|
||||
return err;
|
||||
err = devlink_info_version_running_put(req,
|
||||
DEVLINK_INFO_VERSION_GENERIC_FW,
|
||||
version_str);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* no pending version, return running (stored) version */
|
||||
if (stored_fw == 0)
|
||||
stored_fw = running_fw;
|
||||
|
||||
snprintf(version_str, sizeof(version_str), "%d.%d.%04d",
|
||||
crete_fw_ver_major(stored_fw), crete_fw_ver_minor(stored_fw),
|
||||
crete_fw_ver_subminor(stored_fw));
|
||||
err = devlink_info_version_stored_put(req, "fw.version", version_str);
|
||||
if (err)
|
||||
return err;
|
||||
return devlink_info_version_stored_put(req,
|
||||
DEVLINK_INFO_VERSION_GENERIC_FW,
|
||||
version_str);
|
||||
}
|
||||
|
||||
|
||||
static struct devlink_ops crete_pf_dl_ops = {
|
||||
.eswitch_mode_set = crete_devlink_eswitch_mode_set,
|
||||
.eswitch_mode_get = crete_devlink_eswitch_mode_get,
|
||||
.info_get = crete_devlink_info_get,
|
||||
.flash_update = crete_devlink_flash_update,
|
||||
};
|
||||
|
||||
|
||||
static struct devlink_ops crete_dft_dl_ops;
|
||||
|
||||
|
||||
struct devlink *crete_devlink_alloc(struct device *dev, bool is_pf)
|
||||
{
|
||||
struct devlink_ops *dl_ops;
|
||||
|
||||
if (is_pf)
|
||||
dl_ops = &crete_pf_dl_ops;
|
||||
else
|
||||
dl_ops = &crete_dft_dl_ops;
|
||||
|
||||
#ifndef NEED_DEVLINK_ALLOC_SETS_DEV
|
||||
return devlink_alloc(dl_ops, sizeof(struct crete_core_dev),
|
||||
dev);
|
||||
#else
|
||||
return devlink_alloc(dl_ops, sizeof(struct crete_core_dev));
|
||||
#endif
|
||||
}
|
||||
|
||||
void crete_devlink_free(struct devlink *devlink)
|
||||
{
|
||||
devlink_free(devlink);
|
||||
}
|
||||
|
||||
bool crete_eth_supported(struct crete_core_dev *core_dev)
|
||||
{
|
||||
if (core_dev->device_type != CRETE_DEVICE_CRETE)
|
||||
return false;
|
||||
if (!crete_have_net_cap(core_dev))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool crete_eth_enabled(struct crete_core_dev *core_dev)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool crete_eth_rep_supported(struct crete_core_dev *core_dev)
|
||||
{
|
||||
if(core_dev->device_type == CRETE_DEVICE_PNIC)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool crete_eth_rep_enabled(struct crete_core_dev *core_dev)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool crete_rdma_supported(struct crete_core_dev *core_dev)
|
||||
{
|
||||
if(core_dev->device_type == CRETE_DEVICE_PNIC)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool crete_rdma_enabled(struct crete_core_dev *core_dev)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool crete_rdma_rep_supported(struct crete_core_dev *core_dev)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool crete_rdma_rep_enabled(struct crete_core_dev *core_dev)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool crete_vnet_supported(struct crete_core_dev *core_dev)
|
||||
{
|
||||
if (core_dev->coredev_type == CRETE_COREDEV_PF)
|
||||
return false;
|
||||
|
||||
if (core_dev->device_type == CRETE_DEVICE_PNIC)
|
||||
return true;
|
||||
|
||||
if (core_dev->device_type != CRETE_DEVICE_CRETE)
|
||||
return false;
|
||||
|
||||
if (!crete_have_net_cap(core_dev))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool crete_vnet_enabled(struct crete_core_dev *core_dev)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool crete_nic_supported(struct crete_core_dev *core_dev)
|
||||
{
|
||||
if (core_dev->device_type != CRETE_DEVICE_PNIC ||
|
||||
!crete_core_is_pf(core_dev))
|
||||
return false;
|
||||
|
||||
if (!crete_have_net_cap(core_dev))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool crete_nic_enabled(struct crete_core_dev *core_dev)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_WITHOUT_DEVLINK_PARAM_ETH
|
||||
static const struct devlink_param enable_eth_param =
|
||||
DEVLINK_PARAM_GENERIC(ENABLE_ETH, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
|
||||
NULL, NULL, NULL);
|
||||
|
||||
static int crete_devlink_eth_param_register(struct devlink *devlink)
|
||||
{
|
||||
struct crete_core_dev *dev = devlink_priv(devlink);
|
||||
union devlink_param_value value;
|
||||
int err;
|
||||
|
||||
if (!crete_eth_supported(dev))
|
||||
return 0;
|
||||
|
||||
err = devlink_param_register(devlink, &enable_eth_param);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
value.vbool = true;
|
||||
devlink_param_driverinit_value_set(devlink,
|
||||
DEVLINK_PARAM_GENERIC_ID_ENABLE_ETH,
|
||||
value);
|
||||
devlink_param_publish(devlink, &enable_eth_param);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void crete_devlink_eth_param_unregister(struct devlink *devlink)
|
||||
{
|
||||
struct crete_core_dev *dev = devlink_priv(devlink);
|
||||
|
||||
if (!crete_eth_supported(dev))
|
||||
return;
|
||||
|
||||
devlink_param_unpublish(devlink, &enable_eth_param);
|
||||
devlink_param_unregister(devlink, &enable_eth_param);
|
||||
}
|
||||
|
||||
static int crete_devlink_enable_rdma_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct crete_core_dev *dev = devlink_priv(devlink);
|
||||
bool new_state = val.vbool;
|
||||
|
||||
if (new_state && !crete_rdma_supported(dev))
|
||||
return -EOPNOTSUPP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct devlink_param enable_rdma_param =
|
||||
DEVLINK_PARAM_GENERIC(ENABLE_RDMA, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
|
||||
NULL, NULL, crete_devlink_enable_rdma_validate);
|
||||
|
||||
static int crete_devlink_rdma_param_register(struct devlink *devlink)
|
||||
{
|
||||
union devlink_param_value value;
|
||||
int err;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_crete_INFINIBAND))
|
||||
return 0;
|
||||
|
||||
err = devlink_param_register(devlink, &enable_rdma_param);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
value.vbool = true;
|
||||
devlink_param_driverinit_value_set(devlink,
|
||||
DEVLINK_PARAM_GENERIC_ID_ENABLE_RDMA,
|
||||
value);
|
||||
devlink_param_publish(devlink, &enable_rdma_param);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void crete_devlink_rdma_param_unregister(struct devlink *devlink)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_crete_INFINIBAND))
|
||||
return;
|
||||
|
||||
devlink_param_unpublish(devlink, &enable_rdma_param);
|
||||
devlink_param_unregister(devlink, &enable_rdma_param);
|
||||
}
|
||||
|
||||
static const struct devlink_param enable_vnet_param =
|
||||
DEVLINK_PARAM_GENERIC(ENABLE_VNET, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
|
||||
NULL, NULL, NULL);
|
||||
|
||||
static int crete_devlink_vnet_param_register(struct devlink *devlink)
|
||||
{
|
||||
struct crete_core_dev *dev = devlink_priv(devlink);
|
||||
union devlink_param_value value;
|
||||
int err;
|
||||
|
||||
if (!crete_vnet_supported(dev))
|
||||
return 0;
|
||||
|
||||
err = devlink_param_register(devlink, &enable_vnet_param);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
value.vbool = true;
|
||||
devlink_param_driverinit_value_set(devlink,
|
||||
DEVLINK_PARAM_GENERIC_ID_ENABLE_VNET,
|
||||
value);
|
||||
devlink_param_publish(devlink, &enable_rdma_param);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void crete_devlink_vnet_param_unregister(struct devlink *devlink)
|
||||
{
|
||||
struct crete_core_dev *dev = devlink_priv(devlink);
|
||||
|
||||
if (!crete_vnet_supported(dev))
|
||||
return;
|
||||
|
||||
devlink_param_unpublish(devlink, &enable_vnet_param);
|
||||
devlink_param_unregister(devlink, &enable_vnet_param);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int crete_devlink_auxdev_params_register(struct devlink *devlink)
|
||||
{
|
||||
#ifndef CONFIG_WITHOUT_DEVLINK_PARAM_ETH
|
||||
int err;
|
||||
|
||||
err = crete_devlink_eth_param_register(devlink);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = crete_devlink_rdma_param_register(devlink);
|
||||
if (err)
|
||||
goto rdma_err;
|
||||
|
||||
err = crete_devlink_vnet_param_register(devlink);
|
||||
if (err)
|
||||
goto vnet_err;
|
||||
return 0;
|
||||
|
||||
vnet_err:
|
||||
crete_devlink_rdma_param_unregister(devlink);
|
||||
rdma_err:
|
||||
crete_devlink_eth_param_unregister(devlink);
|
||||
return err;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void crete_devlink_auxdev_params_unregister(struct devlink *devlink)
|
||||
{
|
||||
#ifndef CONFIG_WITHOUT_DEVLINK_PARAM_ETH
|
||||
crete_devlink_vnet_param_unregister(devlink);
|
||||
crete_devlink_rdma_param_unregister(devlink);
|
||||
crete_devlink_eth_param_unregister(devlink);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int crete_devlink_register(struct devlink *devlink)
|
||||
{
|
||||
int err;
|
||||
struct crete_core_dev *core_dev = devlink_priv(devlink);
|
||||
struct pci_dev *pdev = core_dev->pdev;
|
||||
|
||||
dev_info(&pdev->dev, "devlink register");
|
||||
#ifndef HAVE_DEVLINK_REGISTER_SETS_DEV
|
||||
devlink_register(devlink);
|
||||
err = 0;
|
||||
#else
|
||||
err = devlink_register(devlink, &pdev->dev);
|
||||
#endif
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = crete_devlink_auxdev_params_register(devlink);
|
||||
if (err)
|
||||
goto auxdev_reg_err;
|
||||
|
||||
return 0;
|
||||
|
||||
auxdev_reg_err:
|
||||
devlink_unregister(devlink);
|
||||
return err;
|
||||
}
|
||||
|
||||
void crete_devlink_unregister(struct devlink *devlink)
|
||||
{
|
||||
crete_devlink_auxdev_params_unregister(devlink);
|
||||
devlink_unregister(devlink);
|
||||
}
|
||||
|
||||
|
||||
|
@ -0,0 +1,58 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#ifndef __CRETE_DEVLINK_H__
|
||||
#define __CRETE_DEVLINK_H__
|
||||
|
||||
#include <net/devlink.h>
|
||||
|
||||
struct devlink *crete_devlink_alloc(struct device *dev, bool is_pf);
|
||||
void crete_devlink_free(struct devlink *devlink);
|
||||
int crete_devlink_register(struct devlink *devlink);
|
||||
void crete_devlink_unregister(struct devlink *devlink);
|
||||
|
||||
|
||||
bool crete_eth_supported(struct crete_core_dev *core_dev);
|
||||
bool crete_eth_enabled(struct crete_core_dev *core_dev);
|
||||
bool crete_eth_rep_supported(struct crete_core_dev *core_dev);
|
||||
bool crete_eth_rep_enabled(struct crete_core_dev *core_dev);
|
||||
bool crete_rdma_supported(struct crete_core_dev *core_dev);
|
||||
bool crete_rdma_enabled(struct crete_core_dev *core_dev);
|
||||
bool crete_rdma_rep_supported(struct crete_core_dev *core_dev);
|
||||
bool crete_rdma_rep_enabled(struct crete_core_dev *core_dev);
|
||||
bool crete_vnet_supported(struct crete_core_dev *core_dev);
|
||||
bool crete_vnet_enabled(struct crete_core_dev *core_dev);
|
||||
bool crete_nic_supported(struct crete_core_dev *core_dev);
|
||||
bool crete_nic_enabled(struct crete_core_dev *core_dev);
|
||||
|
||||
|
||||
#endif /* __CRETE_DEVLINK_H__ */
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,295 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __CRETE_ESWITCH_H
|
||||
#define __CRETE_ESWITCH_H
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/if_link.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/xarray.h>
|
||||
#include <net/devlink.h>
|
||||
#include "crete_event.h"
|
||||
|
||||
/* The vport iterator is valid only after vport are initialized in mlx5_eswitch_init.
|
||||
* Borrowed the idea from xa_for_each_marked() but with support for desired last element.
|
||||
*/
|
||||
|
||||
#define crete_esw_for_each_vport(esw, index, vport) \
|
||||
xa_for_each(&((esw)->vports), index, vport)
|
||||
|
||||
#define crete_esw_for_each_rep(esw, i, rep) \
|
||||
xa_for_each(&((esw)->eswoffloads.vport_reps), i, rep)
|
||||
|
||||
#define crete_esw_for_each_entry_marked(xa, index, entry, last, filter) \
|
||||
for (index = 0, entry = xa_find(xa, &index, last, filter); \
|
||||
entry; entry = xa_find_after(xa, &index, last, filter))
|
||||
|
||||
#define crete_esw_for_each_vport_marked(esw, index, vport, last, filter) \
|
||||
crete_esw_for_each_entry_marked(&((esw)->vports), index, vport, last, filter)
|
||||
|
||||
#define crete_esw_for_each_vf_vport(esw, index, vport, last) \
|
||||
crete_esw_for_each_vport_marked(esw, index, vport, last, CRETE_ESW_VPT_VF)
|
||||
|
||||
#define crete_esw_for_each_host_func_vport(esw, index, vport, last) \
|
||||
crete_esw_for_each_vport_marked(esw, index, vport, last, CRETE_ESW_VPT_HOST_FN)
|
||||
|
||||
/* Each mark identifies eswitch vport type.
|
||||
* CRETE_ESW_VPT_HOST_FN is used to identify both PF and VF ports using
|
||||
* a single mark.
|
||||
* MLX5_ESW_VPT_VF identifies a SRIOV VF vport.
|
||||
* MLX5_ESW_VPT_SF identifies SF vport.
|
||||
*/
|
||||
#define CRETE_ESW_VPT_HOST_FN XA_MARK_0
|
||||
#define CRETE_ESW_VPT_VF XA_MARK_1
|
||||
#define CRETE_ESW_VPT_SF XA_MARK_2
|
||||
|
||||
/* stub start*/
|
||||
#define CRETE_MAX_UC_PER_VPORT(dev) (8)
|
||||
#define CRETE_MAX_MC_PER_VPORT(dev) (8)
|
||||
#define CRETE_EVENT_TYPE_NIC_VPORT_CHANGE 0xd
|
||||
#define CRETE_EVENT_TYPE_ESW_FUNCTIONS_CHANGED 0xe
|
||||
#define CRETE_MAX_CFA_CODE (65535)
|
||||
#define CRETE_VF_IDX_INVALID 0xffff
|
||||
|
||||
/* stub end*/
|
||||
#define CRETE_ESWITCH_IGNORE_NUM_VFS (-1)
|
||||
|
||||
struct crete_esw_fun {
|
||||
struct crete_nb nb;
|
||||
u16 num_vfs;
|
||||
};
|
||||
|
||||
/* Vport number for each function must keep unchanged */
|
||||
enum {
|
||||
CRETE_VPORT_PF = 0x0,
|
||||
CRETE_VPORT_FIRST_VF = 0x1,
|
||||
CRETE_VPORT_UPLINK = 0xffff
|
||||
};
|
||||
|
||||
#define VPORT(vfid) (vfid + CRETE_VPORT_FIRST_VF)
|
||||
enum {
|
||||
CRETE_VPORT_STATE_OP_MOD_VNIC_VPORT = 0x0,
|
||||
CRETE_VPORT_STATE_OP_MOD_ESW_VPORT = 0x1,
|
||||
CRETE_VPORT_STATE_OP_MOD_UPLINK = 0x2,
|
||||
};
|
||||
|
||||
struct crete_vport_info {
|
||||
u8 mac[ETH_ALEN];
|
||||
u16 vlan;
|
||||
int link_state;
|
||||
u8 qos;
|
||||
__be16 vlan_proto;
|
||||
u8 spoofchk:1;
|
||||
u8 trusted:1;
|
||||
/* the admin approved vlan list */
|
||||
DECLARE_BITMAP(vlan_trunk_8021q_bitmap, VLAN_N_VID);
|
||||
u32 group;
|
||||
|
||||
};
|
||||
|
||||
/* Vport context events */
|
||||
enum crete_esw_vport_event {
|
||||
CRETE_VPORT_UC_ADDR_CHANGE = BIT(0),
|
||||
CRETE_VPORT_MC_ADDR_CHANGE = BIT(1),
|
||||
CRETE_VPORT_PROMISC_CHANGE = BIT(3),
|
||||
};
|
||||
|
||||
enum {
|
||||
CRETE_VPORT_ADMIN_STATE_DOWN = 0x0,
|
||||
CRETE_VPORT_ADMIN_STATE_UP = 0x1,
|
||||
CRETE_VPORT_ADMIN_STATE_AUTO = 0x2,
|
||||
};
|
||||
|
||||
enum {
|
||||
CRETE_ESWITCH_LEGACY,
|
||||
CRETE_ESWITCH_OFFLOADS
|
||||
};
|
||||
|
||||
enum {
|
||||
REP_UNREGISTERED,
|
||||
REP_REGISTERED,
|
||||
REP_LOADED,
|
||||
};
|
||||
|
||||
#define CRETE_LEGACY_SRIOV_VPORT_EVENTS (CRETE_VPORT_UC_ADDR_CHANGE | \
|
||||
CRETE_VPORT_MC_ADDR_CHANGE | \
|
||||
CRETE_VPORT_PROMISC_CHANGE)
|
||||
|
||||
struct crete_vport {
|
||||
struct crete_core_dev *dev;
|
||||
struct crete_vport_info info;
|
||||
struct work_struct vport_change_handler;
|
||||
|
||||
struct {
|
||||
bool enabled;
|
||||
u32 min_rate;
|
||||
u32 max_rate;
|
||||
struct crete_esw_rate_group *group;
|
||||
|
||||
} qos;
|
||||
|
||||
u16 vport;
|
||||
bool enabled;
|
||||
enum crete_esw_vport_event enabled_events;
|
||||
int index;
|
||||
struct devlink_port *dl_port;
|
||||
};
|
||||
|
||||
enum {
|
||||
CRETE_ESW_FDB_CREATED = BIT(0),
|
||||
};
|
||||
|
||||
struct crete_esw_rep;
|
||||
|
||||
struct crete_esw_offload {
|
||||
struct xarray vport_reps;
|
||||
u16 *cfa_code_map;
|
||||
|
||||
};
|
||||
|
||||
struct crete_vf_rep_stats {
|
||||
u64 packets;
|
||||
u64 bytes;
|
||||
u64 dropped;
|
||||
};
|
||||
|
||||
struct crete_esw_rep {
|
||||
struct crete_core_dev *cdev;
|
||||
struct net_device *dev;
|
||||
struct metadata_dst *dst;
|
||||
u16 vport_idx;
|
||||
u16 tx_cfa_action;
|
||||
u16 rx_cfa_code;
|
||||
u16 sfi_code;
|
||||
|
||||
struct crete_vf_rep_stats rx_stats;
|
||||
struct crete_vf_rep_stats tx_stats;
|
||||
struct crete_eswitch *esw;
|
||||
atomic_t state;
|
||||
};
|
||||
|
||||
struct crete_eswitch {
|
||||
struct crete_core_dev *dev;
|
||||
struct xarray vports;
|
||||
int total_vports; /* nums(PF) + nums(VF) + nums(uplink) */
|
||||
int enabled_vports;
|
||||
int mode; /* legacy or offload */
|
||||
u16 manager_vport; /* vport0(PF) */
|
||||
u16 first_host_vport; /* first vf */
|
||||
|
||||
/* Synchronize between vport change events
|
||||
* and async SRIOV admin state changes
|
||||
*/
|
||||
struct mutex state_lock;
|
||||
/* Protects eswitch mode change that occurs via one or more
|
||||
* user commands, i.e. sriov state change, devlink commands.
|
||||
*/
|
||||
struct rw_semaphore mode_lock;
|
||||
atomic64_t user_count;
|
||||
|
||||
struct workqueue_struct *work_queue; /* vport change handle */
|
||||
|
||||
struct crete_nb nb;
|
||||
struct crete_esw_fun esw_funcs;
|
||||
struct crete_esw_offload eswoffloads;
|
||||
};
|
||||
|
||||
/**
|
||||
* crete_esw_event_info - Indicates eswitch mode changed/changing.
|
||||
*
|
||||
* @new_mode: New mode of eswitch.
|
||||
*/
|
||||
struct crete_esw_event_info {
|
||||
u16 new_mode;
|
||||
};
|
||||
|
||||
/* Init API */
|
||||
int crete_eswitch_init(struct crete_core_dev *dev);
|
||||
void crete_eswitch_cleanup(struct crete_eswitch *esw);
|
||||
|
||||
/* SRIOV API */
|
||||
int crete_eswitch_enable(struct crete_eswitch *esw, int num_vfs);
|
||||
void crete_eswitch_disable_sriov(struct crete_eswitch *esw, bool clear_vf);
|
||||
void crete_eswitch_disable(struct crete_eswitch *esw);
|
||||
void crete_eswitch_disable_locked(struct crete_eswitch *esw);
|
||||
|
||||
/* eswitch vport API */
|
||||
int crete_eswitch_set_vport_mac(struct crete_eswitch *esw,
|
||||
u16 vport, const u8 *mac);
|
||||
int crete_eswitch_set_vport_state(struct crete_eswitch *esw,
|
||||
u16 vport, int link_state);
|
||||
int crete_eswitch_set_vport_vlan(struct crete_eswitch *esw,
|
||||
int vport, u16 vlan, u8 qos,
|
||||
__be16 vlan_proto);
|
||||
int crete_eswitch_set_vport_spoofchk(struct crete_eswitch *esw, u16 vport,
|
||||
bool spoofchk);
|
||||
int crete_eswitch_set_vport_trust(struct crete_eswitch *esw, u16 vport_num,
|
||||
bool setting);
|
||||
int crete_eswitch_set_vport_rate(struct crete_eswitch *esw, u16 vport,
|
||||
u32 max_rate, u32 min_rate);
|
||||
|
||||
/* eswitch rw lock API */
|
||||
bool crete_esw_hold(struct crete_core_dev *dev);
|
||||
void crete_esw_release(struct crete_core_dev *dev);
|
||||
void crete_esw_get(struct crete_core_dev *dev);
|
||||
void crete_esw_put(struct crete_core_dev *dev);
|
||||
int crete_esw_try_lock(struct crete_eswitch *esw);
|
||||
void crete_esw_unlock(struct crete_eswitch *esw);
|
||||
|
||||
/* devlink API */
|
||||
int esw_offloads_start(struct crete_eswitch *esw,
|
||||
struct netlink_ext_ack *extack);
|
||||
int esw_offloads_stop(struct crete_eswitch *esw,
|
||||
struct netlink_ext_ack *extack);
|
||||
|
||||
struct crete_vport *crete_eswitch_get_vport(struct crete_eswitch *esw,
|
||||
u16 vport_num);
|
||||
|
||||
int crete_eswitch_add_vport_trunk_range(struct crete_eswitch *esw,
|
||||
int vport, u16 start_vlan,
|
||||
u16 end_vlan);
|
||||
|
||||
int crete_eswitch_del_vport_trunk_range(struct crete_eswitch *esw,
|
||||
int vport, u16 start_vlan,
|
||||
u16 end_vlan);
|
||||
|
||||
int crete_esw_qos_set_sysfs_group_max_rate(struct crete_eswitch *esw,
|
||||
struct crete_esw_rate_group *group,
|
||||
u32 max_rate);
|
||||
int crete_esw_qos_set_sysfs_group_min_rate(struct crete_eswitch *esw,
|
||||
struct crete_esw_rate_group *group,
|
||||
u32 min_rate);
|
||||
int crete_esw_qos_vport_update_sysfs_group(struct crete_eswitch *esw,
|
||||
int vport_num, u32 group_id);
|
||||
|
||||
#endif /* __CRETE_ESWITCH_H */
|
@ -0,0 +1,236 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <net/devlink.h>
|
||||
#include <linux/xarray.h>
|
||||
#include "crete.h"
|
||||
#include "crete_eswitch.h"
|
||||
#include "crete_rep.h"
|
||||
|
||||
int crete_offloads_rep_cleanup(struct crete_eswitch *esw)
|
||||
{
|
||||
struct crete_esw_rep *rep;
|
||||
unsigned long i;
|
||||
|
||||
crete_esw_for_each_rep(esw, i, rep) {
|
||||
xa_erase(&esw->eswoffloads.vport_reps, rep->vport_idx);
|
||||
kfree(rep);
|
||||
}
|
||||
|
||||
xa_destroy(&esw->eswoffloads.vport_reps);
|
||||
kfree(esw->eswoffloads.cfa_code_map);
|
||||
esw->eswoffloads.cfa_code_map = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* crete offloads representors initial
|
||||
* init the offloads reps xarray
|
||||
* alloc the reps struct and cfa code map
|
||||
*/
|
||||
int crete_offloads_rep_init(struct crete_eswitch *esw)
|
||||
{
|
||||
struct crete_vport *vport;
|
||||
struct crete_esw_rep *rep;
|
||||
unsigned long i;
|
||||
int err;
|
||||
|
||||
xa_init(&esw->eswoffloads.vport_reps);
|
||||
|
||||
crete_esw_for_each_vport(esw, i, vport) {
|
||||
rep = kzalloc(sizeof(*rep), GFP_KERNEL);
|
||||
if (!rep) {
|
||||
err = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
rep->vport_idx = vport->index;
|
||||
atomic_set(&rep->state, REP_UNREGISTERED);
|
||||
|
||||
err =
|
||||
xa_insert(&esw->eswoffloads.vport_reps, vport->index, rep,
|
||||
GFP_KERNEL);
|
||||
if (err) {
|
||||
kfree(rep);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
esw->eswoffloads.cfa_code_map = kcalloc(CRETE_MAX_CFA_CODE,
|
||||
sizeof(*esw->eswoffloads.cfa_code_map), GFP_KERNEL);
|
||||
if (!esw->eswoffloads.cfa_code_map) {
|
||||
err = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (i = 0; i < CRETE_MAX_CFA_CODE; i++)
|
||||
esw->eswoffloads.cfa_code_map[i] = CRETE_VF_IDX_INVALID;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
crete_offloads_rep_cleanup(esw);
|
||||
return err;
|
||||
}
|
||||
|
||||
void crete_unload_reps_all_vport(struct crete_eswitch *esw)
|
||||
{
|
||||
struct crete_esw_rep *rep;
|
||||
unsigned long i;
|
||||
|
||||
crete_esw_for_each_rep(esw, i, rep) {
|
||||
|
||||
if (atomic_read(&rep->state) != REP_LOADED)
|
||||
continue;
|
||||
|
||||
crete_alloc_vf_rep_unload(esw->dev, rep);
|
||||
|
||||
atomic_set(&rep->state, REP_REGISTERED);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int crete_load_reps_all_vport(struct crete_eswitch *esw)
|
||||
{
|
||||
struct crete_esw_rep *rep;
|
||||
unsigned long i;
|
||||
int err;
|
||||
|
||||
crete_esw_for_each_rep(esw, i, rep) {
|
||||
|
||||
/* not exceed the max enable vf numbers */
|
||||
if (i >= esw->esw_funcs.num_vfs)
|
||||
break;
|
||||
/* check the rep is registered */
|
||||
if (atomic_read(&rep->state) != REP_REGISTERED)
|
||||
continue;
|
||||
|
||||
if (crete_alloc_vf_rep_load(esw->dev, rep)) {
|
||||
err = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
atomic_set(&rep->state, REP_LOADED);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
crete_unload_reps_all_vport(esw);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void crete_eswitch_register_vport_reps(struct crete_eswitch *esw)
|
||||
{
|
||||
struct crete_esw_rep *rep;
|
||||
unsigned long i;
|
||||
|
||||
crete_esw_for_each_rep(esw, i, rep) {
|
||||
rep->esw = esw;
|
||||
atomic_set(&rep->state, REP_REGISTERED);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void crete_eswitch_unregister_vport_reps(struct crete_eswitch *esw)
|
||||
{
|
||||
struct crete_esw_rep *rep;
|
||||
unsigned long i;
|
||||
|
||||
if (esw->mode == CRETE_ESWITCH_OFFLOADS)
|
||||
crete_unload_reps_all_vport(esw);
|
||||
|
||||
crete_esw_for_each_rep(esw, i, rep)
|
||||
atomic_set(&rep->state, REP_UNREGISTERED);
|
||||
|
||||
}
|
||||
|
||||
static int crete_rep_probe(struct auxiliary_device *adev,
|
||||
const struct auxiliary_device_id *id)
|
||||
{
|
||||
struct crete_aux_dev *aux_dev =
|
||||
container_of(adev, struct crete_aux_dev, adev);
|
||||
struct crete_core_dev *cdev = aux_dev->core_dev;
|
||||
struct crete_eswitch *esw = cdev->eswitch;
|
||||
|
||||
/* rep init */
|
||||
crete_eswitch_register_vport_reps(esw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* about the anolis 5.10.134-14 kernel version
|
||||
* auxliary define with return int value
|
||||
*/
|
||||
#ifdef SNIC_ANOLIS_VERSION14
|
||||
|
||||
static int crete_rep_remove(struct auxiliary_device *adev)
|
||||
{
|
||||
struct crete_aux_dev *aux_dev =
|
||||
container_of(adev, struct crete_aux_dev, adev);
|
||||
|
||||
crete_eswitch_unregister_vport_reps(aux_dev->core_dev->eswitch);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void crete_rep_remove(struct auxiliary_device *adev)
|
||||
{
|
||||
struct crete_aux_dev *aux_dev =
|
||||
container_of(adev, struct crete_aux_dev, adev);
|
||||
|
||||
crete_eswitch_unregister_vport_reps(aux_dev->core_dev->eswitch);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static const struct auxiliary_device_id crete_rep_id_table[] = {
|
||||
{.name = CRETE_ADEV_NAME ".eth-rep", },
|
||||
{ }
|
||||
};
|
||||
|
||||
struct auxiliary_driver crete_rep_driver = {
|
||||
.name = CRETE_ADEV_NAME ".eth-rep",
|
||||
.probe = crete_rep_probe,
|
||||
.remove = crete_rep_remove,
|
||||
.id_table = crete_rep_id_table,
|
||||
};
|
@ -0,0 +1,42 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __ESWOFFLOADS_
|
||||
#define __ESWOFFLOADS_
|
||||
|
||||
int crete_offloads_rep_cleanup(struct crete_eswitch *esw);
|
||||
int crete_offloads_rep_init(struct crete_eswitch *esw);
|
||||
int crete_load_reps_all_vport(struct crete_eswitch *esw);
|
||||
void crete_unload_reps_all_vport(struct crete_eswitch *esw);
|
||||
|
||||
#endif
|
@ -0,0 +1,308 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/ethtool_netlink.h>
|
||||
#include <linux/firmware.h>
|
||||
#include "crete.h"
|
||||
#include "crete_cmd_if.h"
|
||||
#include "crete_regs.h"
|
||||
#include "crete_fw_update.h"
|
||||
|
||||
struct crete_stats_desc {
|
||||
char desc[ETH_GSTRING_LEN];
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
struct crete_stats_desc crete_txq_stats_desc[] = {
|
||||
{"packets", CRETE_TXQ_STATS(packets)},
|
||||
{"bytes", CRETE_TXQ_STATS(bytes)},
|
||||
{"kicks", CRETE_TXQ_STATS(kicks)},
|
||||
};
|
||||
|
||||
struct crete_stats_desc crete_rxq_stats_desc[] = {
|
||||
{"packets", CRETE_RXQ_STATS(packets)},
|
||||
{"bytes", CRETE_RXQ_STATS(bytes)},
|
||||
{"drops", CRETE_RXQ_STATS(drops)},
|
||||
{"kicks", CRETE_RXQ_STATS(kicks)},
|
||||
};
|
||||
|
||||
#define CRETE_TXQ_STATS_LEN ARRAY_SIZE(crete_txq_stats_desc)
|
||||
#define CRETE_RXQ_STATS_LEN ARRAY_SIZE(crete_rxq_stats_desc)
|
||||
|
||||
void crete_ethtool_get_drvinfo(struct crete_priv *priv,
|
||||
struct ethtool_drvinfo *drvinfo)
|
||||
{
|
||||
struct crete_core_dev *coredev = priv->coredev;
|
||||
int count;
|
||||
|
||||
strscpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver));
|
||||
snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
|
||||
"%d.%d.%d.%d", fw_ver_maj(coredev),
|
||||
fw_ver_min(coredev), fw_ver_sub(coredev), fw_ver_rev(coredev));
|
||||
|
||||
strscpy(drvinfo->bus_info, dev_name(&coredev->pdev->dev),
|
||||
sizeof(drvinfo->bus_info));
|
||||
}
|
||||
|
||||
static void crete_get_drvinfo(struct net_device *dev,
|
||||
struct ethtool_drvinfo *drvinfo)
|
||||
{
|
||||
struct crete_priv *priv = netdev_priv(dev);
|
||||
|
||||
crete_ethtool_get_drvinfo(priv, drvinfo);
|
||||
}
|
||||
|
||||
static void get_speed_duplex(struct net_device *netdev,
|
||||
struct ethtool_link_ksettings *link_ksettings)
|
||||
{
|
||||
u32 speed = SPEED_UNKNOWN;
|
||||
u8 duplex = DUPLEX_UNKNOWN;
|
||||
|
||||
if (!netif_carrier_ok(netdev))
|
||||
goto out;
|
||||
|
||||
/* get speed TODO */
|
||||
|
||||
duplex = DUPLEX_FULL;
|
||||
|
||||
out:
|
||||
link_ksettings->base.speed = speed;
|
||||
link_ksettings->base.duplex = duplex;
|
||||
}
|
||||
|
||||
int crete_ethtool_get_link_ksettings(struct crete_priv *priv,
|
||||
struct ethtool_link_ksettings *link_ksettings)
|
||||
{
|
||||
ethtool_link_ksettings_zero_link_mode(link_ksettings, supported);
|
||||
ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising);
|
||||
|
||||
get_speed_duplex(priv->netdev, link_ksettings);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int crete_get_link_ksettings(struct net_device *netdev,
|
||||
struct ethtool_link_ksettings *link_ksettings)
|
||||
{
|
||||
struct crete_priv *priv = netdev_priv(netdev);
|
||||
|
||||
return crete_ethtool_get_link_ksettings(priv, link_ksettings);
|
||||
}
|
||||
|
||||
int crete_ethtool_set_link_ksettings(struct crete_priv *priv,
|
||||
const struct ethtool_link_ksettings *link_ksettings)
|
||||
{
|
||||
struct crete_core_dev *cdev = priv->coredev;
|
||||
u32 speed;
|
||||
|
||||
speed = link_ksettings->base.speed;
|
||||
crete_info(&cdev->pdev->dev, "set link speed:%u\n", speed);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int crete_set_link_ksettings(struct net_device *netdev,
|
||||
const struct ethtool_link_ksettings *link_ksettings)
|
||||
{
|
||||
struct crete_priv *priv = netdev_priv(netdev);
|
||||
|
||||
return crete_ethtool_set_link_ksettings(priv, link_ksettings);
|
||||
}
|
||||
|
||||
int crete_ethtool_set_pauseparam(struct crete_priv *priv,
|
||||
struct ethtool_pauseparam *pauseparam)
|
||||
{
|
||||
struct crete_core_dev *cdev = priv->coredev;
|
||||
int err;
|
||||
|
||||
// if (pauseparam->autoneg)
|
||||
// return -EINVAL;
|
||||
|
||||
err = crete_set_fc_enable(cdev, 1,
|
||||
pauseparam->rx_pause ? 1 : 0,
|
||||
pauseparam->tx_pause ? 1 : 0);
|
||||
if (err) {
|
||||
netdev_err(priv->netdev, "%s: crete_set_fc_enable failed:0x%x\n",
|
||||
__func__, err);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int crete_query_port_pause(struct crete_core_dev *dev,
|
||||
u32 *rx_pause, u32 *tx_pause)
|
||||
{
|
||||
*rx_pause = 0;
|
||||
*tx_pause = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void crete_ethtool_get_pauseparam(struct crete_priv *priv,
|
||||
struct ethtool_pauseparam *pauseparam)
|
||||
{
|
||||
struct crete_core_dev *cdev = priv->coredev;
|
||||
int err;
|
||||
|
||||
err = crete_query_port_pause(cdev, &pauseparam->rx_pause,
|
||||
&pauseparam->tx_pause);
|
||||
if (err) {
|
||||
netdev_err(priv->netdev, "%s: crete_query_port_pause failed:0x%x\n",
|
||||
__func__, err);
|
||||
}
|
||||
}
|
||||
|
||||
static int crete_set_pauseparam(struct net_device *netdev,
|
||||
struct ethtool_pauseparam *pauseparam)
|
||||
{
|
||||
struct crete_priv *priv = netdev_priv(netdev);
|
||||
|
||||
return crete_ethtool_set_pauseparam(priv, pauseparam);
|
||||
}
|
||||
|
||||
void crete_get_pauseparam(struct net_device *netdev,
|
||||
struct ethtool_pauseparam *pauseparam)
|
||||
{
|
||||
struct crete_priv *priv = netdev_priv(netdev);
|
||||
|
||||
crete_ethtool_get_pauseparam(priv, pauseparam);
|
||||
}
|
||||
|
||||
int crete_ethtool_flash_device(struct crete_priv *priv,
|
||||
struct ethtool_flash *flash)
|
||||
{
|
||||
struct crete_core_dev *cdev = priv->coredev;
|
||||
struct net_device *dev = priv->netdev;
|
||||
const struct firmware *fw;
|
||||
int err;
|
||||
|
||||
if (flash->region != ETHTOOL_FLASH_ALL_REGIONS)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
err = request_firmware_direct(&fw, flash->data, &dev->dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
dev_hold(dev);
|
||||
rtnl_unlock();
|
||||
|
||||
err = crete_firmware_flash(cdev, fw, NULL, CRETE_FWU_ETHTOOL);
|
||||
release_firmware(fw);
|
||||
|
||||
rtnl_lock();
|
||||
dev_put(dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static int crete_flash_device(struct net_device *dev,
|
||||
struct ethtool_flash *flash)
|
||||
{
|
||||
struct crete_priv *priv = netdev_priv(dev);
|
||||
|
||||
return crete_ethtool_flash_device(priv, flash);
|
||||
}
|
||||
|
||||
static void crete_get_strings(struct net_device *dev, u32 stringset, u8 *data)
|
||||
{
|
||||
struct crete_priv *priv = netdev_priv(dev);
|
||||
struct crete_core_dev *cdev = priv->coredev;
|
||||
char *p = (char *)data;
|
||||
unsigned int i, j;
|
||||
|
||||
switch (stringset) {
|
||||
case ETH_SS_STATS:
|
||||
for (i = 0; i < cdev->ring_size; i++) {
|
||||
for (j = 0; j < CRETE_RXQ_STATS_LEN; j++) {
|
||||
snprintf(p, ETH_GSTRING_LEN, "rx_queue_%u_%s",
|
||||
i, crete_rxq_stats_desc[j].desc);
|
||||
p += ETH_GSTRING_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < cdev->ring_size; i++) {
|
||||
for (j = 0; j < CRETE_TXQ_STATS_LEN; j++) {
|
||||
snprintf(p, ETH_GSTRING_LEN, "tx_queue_%u_%s",
|
||||
i, crete_txq_stats_desc[j].desc);
|
||||
p += ETH_GSTRING_LEN;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void crete_get_ethtool_stats(struct net_device *dev,
|
||||
struct ethtool_stats *stats, u64 *data)
|
||||
{
|
||||
struct crete_priv *priv = netdev_priv(dev);
|
||||
struct crete_core_dev *cdev = priv->coredev;
|
||||
unsigned int idx = 0, start, i, j;
|
||||
const u8 *stats_base;
|
||||
size_t offset;
|
||||
|
||||
for (i = 0; i < cdev->ring_size; i++) {
|
||||
stats_base = (u8 *)cdev->rxring[i].rxq_stats;
|
||||
do {
|
||||
start = u64_stats_fetch_begin_irq(&cdev->rxring[i].rxq_stats->syncp);
|
||||
for (j = 0; j < CRETE_RXQ_STATS_LEN; j++) {
|
||||
offset = crete_rxq_stats_desc[j].offset;
|
||||
data[idx + j] = *(u64 *) (stats_base + offset);
|
||||
}
|
||||
} while (u64_stats_fetch_retry_irq(&cdev->rxring[i].rxq_stats->syncp, start));
|
||||
idx += CRETE_RXQ_STATS_LEN;
|
||||
}
|
||||
|
||||
for (i = 0; i < cdev->ring_size; i++) {
|
||||
stats_base = (u8 *)&cdev->txring[i].txq_stats;
|
||||
do {
|
||||
start = u64_stats_fetch_begin_irq(&cdev->txring[i].txq_stats->syncp);
|
||||
for (j = 0; j < CRETE_TXQ_STATS_LEN; j++) {
|
||||
offset = crete_txq_stats_desc[j].offset;
|
||||
data[idx + j] = *(u64 *) (stats_base + offset);
|
||||
}
|
||||
} while (u64_stats_fetch_retry_irq(&cdev->txring[i].txq_stats->syncp, start));
|
||||
idx += CRETE_TXQ_STATS_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
const struct ethtool_ops crete_ethtool_ops = {
|
||||
.get_drvinfo = crete_get_drvinfo,
|
||||
.get_link_ksettings = crete_get_link_ksettings,
|
||||
.set_link_ksettings = crete_set_link_ksettings,
|
||||
//.get_pauseparam = crete_get_pauseparam,
|
||||
.set_pauseparam = crete_set_pauseparam,
|
||||
.flash_device = crete_flash_device,
|
||||
.get_strings = crete_get_strings,
|
||||
.get_ethtool_stats = crete_get_ethtool_stats,
|
||||
};
|
||||
|
@ -0,0 +1,85 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __CRETE_ETHTOOL_COMMON_H__
|
||||
#define __CRETE_ETHTOOL_COMMON_H__
|
||||
|
||||
#include "crete.h"
|
||||
#include <linux/ethtool.h>
|
||||
|
||||
#define AUTO_NEG_OP_BIT BIT(2)
|
||||
#define DUPLEX_MODE_OP_BIT BIT(1)
|
||||
#define LINK_SPEED_OP_BIT BIT(0)
|
||||
|
||||
enum crete_link_mode {
|
||||
CRETE_10GBASE = 1,
|
||||
CRETE_25GBASE,
|
||||
CRETE_40GBASE,
|
||||
CRETE_50GBASE,
|
||||
CRETE_100GBASE,
|
||||
CRETE_200GBASE,
|
||||
CRETE_400GBASE,
|
||||
CRETE_LINK_MODES_NUMBER,
|
||||
};
|
||||
|
||||
enum crete_link_mode_bit {
|
||||
CRETE_10GBASE_BIT,
|
||||
CRETE_25GBASE_BIT,
|
||||
CRETE_40GBASE_BIT,
|
||||
CRETE_50GBASE_BIT,
|
||||
CRETE_100GBASE_BIT,
|
||||
CRETE_200GBASE_BIT,
|
||||
CRETE_400GBASE_BIT,
|
||||
CRETE_LINK_MODES_CAP_BIT,
|
||||
};
|
||||
|
||||
enum crete_duplex {
|
||||
CRETE_HALF_DUPLEX,
|
||||
CRETE_FULL_DUPLEX,
|
||||
CRETE_DUPLEX_MAX,
|
||||
};
|
||||
enum crete_fec_mode {
|
||||
CRETE_FEC_OFF = 0,
|
||||
CRETE_FEC_AUTO,
|
||||
CRETE_FEC_RS,
|
||||
CRETE_FEC_BASER,
|
||||
CRETE_FEC_LLRS,
|
||||
};
|
||||
|
||||
static const u32 crete_link_speed[CRETE_LINK_MODES_NUMBER] = {
|
||||
0,
|
||||
[CRETE_10GBASE] = SPEED_10000,
|
||||
[CRETE_25GBASE] = SPEED_25000,
|
||||
[CRETE_40GBASE] = SPEED_40000,
|
||||
[CRETE_50GBASE] = SPEED_50000,
|
||||
[CRETE_100GBASE] = SPEED_100000,
|
||||
[CRETE_200GBASE] = SPEED_200000,
|
||||
[CRETE_400GBASE] = SPEED_400000,
|
||||
};
|
||||
|
||||
static const u32 crete_fec_2_ethtool[] = {
|
||||
[CRETE_FEC_OFF] = ETHTOOL_FEC_OFF,
|
||||
[CRETE_FEC_AUTO] = ETHTOOL_FEC_AUTO,
|
||||
[CRETE_FEC_RS] = ETHTOOL_FEC_RS,
|
||||
[CRETE_FEC_BASER] = ETHTOOL_FEC_BASER,
|
||||
[CRETE_FEC_LLRS] = ETHTOOL_FEC_LLRS,
|
||||
};
|
||||
|
||||
static const u32 crete_fec_2_ethtool_bit[] = {
|
||||
[CRETE_FEC_OFF] = ETHTOOL_LINK_MODE_FEC_NONE_BIT,
|
||||
[CRETE_FEC_RS] = ETHTOOL_LINK_MODE_FEC_RS_BIT,
|
||||
[CRETE_FEC_BASER] = ETHTOOL_LINK_MODE_FEC_BASER_BIT,
|
||||
[CRETE_FEC_LLRS] = ETHTOOL_LINK_MODE_FEC_LLRS_BIT,
|
||||
};
|
||||
|
||||
static const u8 crete_link_duplex[CRETE_DUPLEX_MAX] = {
|
||||
[CRETE_HALF_DUPLEX] = DUPLEX_HALF,
|
||||
[CRETE_FULL_DUPLEX] = DUPLEX_FULL,
|
||||
};
|
||||
|
||||
struct crete_speed_duplex {
|
||||
uint16_t speed;
|
||||
uint16_t duplex;
|
||||
uint32_t duplex_cap;
|
||||
uint32_t speed_cap;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,232 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "crete.h"
|
||||
#include "crete_cmd.h"
|
||||
#include "crete_regs.h"
|
||||
|
||||
#define EVNET_IN_MASK 0x02
|
||||
#define EVNET_BUSY_MASK 0x01
|
||||
#define EVNET_NO_BUSY_MASK 0xFE
|
||||
|
||||
static irqreturn_t irq_int_handler(int irq, void *dev)
|
||||
{
|
||||
struct crete_core_dev *cdev = (struct crete_core_dev *)dev;
|
||||
struct crete_event_irq *event_irq = cdev->event_irq;
|
||||
struct crete_event_entry cee;
|
||||
struct crete_event_buffer_head event_buffer_head;
|
||||
struct crete_hw *hw = &cdev->hw;
|
||||
uint32_t total_len_dw;
|
||||
uint32_t index = 1;
|
||||
uint8_t val = 0;
|
||||
bool device_owner = false;
|
||||
bool buf_inline = false;
|
||||
|
||||
val = readb(&hw->io_addr->event_busy);
|
||||
if (val & EVNET_BUSY_MASK) {
|
||||
device_owner = true;
|
||||
buf_inline = !!(val & EVNET_IN_MASK);
|
||||
} else {
|
||||
dev_err(cdev->device, "device is not set owner!\n");
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
if(!buf_inline) {
|
||||
dev_err(cdev->device, "current not support not inline!\n");
|
||||
writeb(val & EVNET_NO_BUSY_MASK, &hw->io_addr->event_busy);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
crete_ioread32(&hw->io_addr->event_buffer[0],
|
||||
&event_buffer_head, 1);
|
||||
total_len_dw = event_buffer_head.event_entry_length;
|
||||
|
||||
memset(&cee, 0, sizeof(struct crete_event_entry));
|
||||
while (index <= total_len_dw) {
|
||||
crete_ioread32(&hw->io_addr->event_buffer[index], &cee, 1);
|
||||
if (cee.event_length)
|
||||
crete_ioread32(&hw->io_addr->event_buffer[index+1],
|
||||
cee.event_data, cee.event_length);
|
||||
atomic_notifier_call_chain(&event_irq->nh[cee.event_type], cee.event_type, &cee);
|
||||
pr_info("crete event handle event type:%u\n", cee.event_type);
|
||||
index += (cee.event_length + 1);
|
||||
}
|
||||
writeb(val & EVNET_NO_BUSY_MASK, &hw->io_addr->event_busy);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
int crete_event_alloc_buf(struct crete_core_dev *cdev,
|
||||
struct crete_event_irq *event_irq)
|
||||
{
|
||||
struct crete_hw *hw = &cdev->hw;
|
||||
size_t size = CRETE_EVENT_ALLOC_BUFFER_SIZE * sizeof(uint32_t);
|
||||
|
||||
event_irq->event_buf_size = size;
|
||||
crete_info(cdev->device, "event_irq->event_buf_size:%ld", size);
|
||||
|
||||
event_irq->event_buf = dma_alloc_coherent(cdev->device, CRETE_EVENT_ALLOC_BUFFER_SIZE*4,
|
||||
&event_irq->event_dma, GFP_KERNEL | __GFP_ZERO);
|
||||
if (!event_irq->event_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
crete_info(cdev->device, "event buffer dma addr:0x%llx\n", event_irq->event_dma);
|
||||
|
||||
iseg_wd8(hw, struct crete_init_seg,
|
||||
event_buffer_size, (u8)(event_irq->event_buf_size));
|
||||
|
||||
iseg_wd32(hw, struct crete_init_seg, event_buffer_addr_low,
|
||||
(u32)(event_irq->event_dma & 0xffffffff));
|
||||
|
||||
iseg_wd32(hw, struct crete_init_seg,
|
||||
event_buffer_addr_hi, (u32)(event_irq->event_dma >> 32));
|
||||
|
||||
/* Make sure firmware sees the complete address before we proceed */
|
||||
wmb();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int crete_event_start(struct crete_hw *hw)
|
||||
{
|
||||
int i, err, irqno;
|
||||
struct crete_event_irq *event_irq;
|
||||
struct crete_core_dev *cdev = container_of(hw,
|
||||
struct crete_core_dev, hw);
|
||||
struct device *dev = crete_hw_to_dev(hw);
|
||||
struct crete_irq_info *irq_info = NULL;
|
||||
struct msix_entry *msix_ent = NULL;
|
||||
|
||||
irqno = crete_req_msixirq(cdev);
|
||||
irq_info = &cdev->irq_info[irqno];
|
||||
msix_ent = &cdev->msix_ent[irqno];
|
||||
|
||||
if (!(cdev->flags & CRETE_FLAG_HAS_MSIX))
|
||||
return 0;
|
||||
|
||||
event_irq = kzalloc(sizeof(*event_irq), GFP_KERNEL);
|
||||
if (!event_irq)
|
||||
return -ENOMEM;
|
||||
|
||||
#ifndef CONFIG_NOSIM_DEBUG
|
||||
writew(irqno, &hw->io_addr->event_vector);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < CRETE_EVENT_TYPE_MAX; i++)
|
||||
ATOMIC_INIT_NOTIFIER_HEAD(&event_irq->nh[i]);
|
||||
|
||||
snprintf(event_irq->name, sizeof(event_irq->name), "event@pci:%s", pci_name(cdev->pdev));
|
||||
crete_info(dev, "event_irq_name[%s]", event_irq->name);
|
||||
event_irq->vector = irq_info->vector;
|
||||
event_irq->entry = irqno;
|
||||
cdev->event_irq = event_irq;
|
||||
|
||||
err = request_irq(event_irq->vector, irq_int_handler, 0, event_irq->name, cdev);
|
||||
if (err) {
|
||||
crete_err(dev, "Failed to request irq. err = %d\n", err);
|
||||
goto err_req_irq;
|
||||
}
|
||||
irq_info->requested = 1;
|
||||
irq_info->handler = irq_int_handler;
|
||||
crete_info(dev, "crete_event init success event_irq_name[%s], vector[%d], irq[%d]",
|
||||
event_irq->name, irqno, event_irq->vector);
|
||||
return 0;
|
||||
|
||||
err_req_irq:
|
||||
crete_free_msixirq(cdev, irqno);
|
||||
|
||||
kfree(event_irq);
|
||||
return err;
|
||||
}
|
||||
|
||||
int crete_event_notifier_register(struct crete_core_dev *dev, struct crete_nb *nb)
|
||||
{
|
||||
struct crete_event_irq *irq_nb = dev->event_irq;
|
||||
|
||||
return atomic_notifier_chain_register(&irq_nb->nh[nb->event_type], &nb->nb);
|
||||
}
|
||||
EXPORT_SYMBOL(crete_event_notifier_register);
|
||||
|
||||
int crete_event_notifier_unregister(struct crete_core_dev *dev, struct crete_nb *nb)
|
||||
{
|
||||
struct crete_event_irq *irq_nb = dev->event_irq;
|
||||
|
||||
return atomic_notifier_chain_unregister(&irq_nb->nh[nb->event_type], &nb->nb);
|
||||
}
|
||||
EXPORT_SYMBOL(crete_event_notifier_unregister);
|
||||
|
||||
int crete_event_init(struct crete_hw *hw)
|
||||
{
|
||||
int err = 0;
|
||||
uint8_t val;
|
||||
struct device *dev = crete_hw_to_dev(hw);
|
||||
val = readb(&hw->io_addr->cp_caps);
|
||||
if (val & CRETE_CP_EP) {
|
||||
err = crete_event_start(hw);
|
||||
if (err < 0) {
|
||||
crete_info(dev, "crete_event_start failed!\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
val = readb(&hw->io_addr->cp_status);
|
||||
val |= CRETE_CP_EP;
|
||||
writeb(val, &hw->io_addr->cp_status);
|
||||
} else {
|
||||
crete_info(dev, "not support event path!\n");
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void crete_event_exit(struct crete_hw *hw)
|
||||
{
|
||||
struct crete_irq_info *irq_info;
|
||||
struct crete_core_dev *cdev = container_of(hw,
|
||||
struct crete_core_dev, hw);
|
||||
struct device *dev = crete_hw_to_dev(hw);
|
||||
|
||||
if (!cdev->event_irq) {
|
||||
crete_info(dev, "crete event already exit\n");
|
||||
return;
|
||||
}
|
||||
|
||||
irq_info = &cdev->irq_info[cdev->event_irq->entry];
|
||||
|
||||
if (irq_info->requested) {
|
||||
crete_free_msixirq(cdev, cdev->event_irq->vector);
|
||||
free_irq(irq_info->vector, cdev);
|
||||
kfree(cdev->event_irq);
|
||||
cdev->event_irq = NULL;
|
||||
}
|
||||
|
||||
crete_info(dev, "crete event exit\n");
|
||||
}
|
||||
EXPORT_SYMBOL(crete_event_exit);
|
@ -0,0 +1,128 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _CRETE_EVENT_H
|
||||
#define _CRETE_EVENT_H
|
||||
|
||||
#include "crete.h"
|
||||
#include <linux/types.h>
|
||||
#include <uapi/linux/stddef.h>
|
||||
|
||||
|
||||
#define CRETE_MAX_IRQ_NAME 32
|
||||
#define CRETE_EVENT_ALLOC_BUFFER_SIZE 8
|
||||
|
||||
#define CRETE_EVENT_SUPPORTED(hw) (readb(&(hw)->io_addr->cp_caps) & CRETE_CP_EP)
|
||||
|
||||
|
||||
// enum crete_event_offset {
|
||||
// CRETE_EVENT_TYPE_CMDPATH = 0,
|
||||
// CRETE_EVENT_TYPE_ADMIN = 1,
|
||||
|
||||
// };
|
||||
|
||||
enum crete_event_type {
|
||||
/* Completion group */
|
||||
CRETE_EVENT_TYPE_CP = 0,
|
||||
/* status Change group */
|
||||
/* Error Report group */
|
||||
/* Data transfer group */
|
||||
CRETE_EVENT_PTP_TIMESTAMP = 1,
|
||||
CRETE_EVENT_PORT_LINK_CHANGE = 0x201,
|
||||
CRETE_EVENT_TYPE_MAX,
|
||||
};
|
||||
|
||||
enum crete_vnet_evnet_subtype {
|
||||
CRETE_EVENT_VNET_LINK_CHANGE = 0,
|
||||
CRETE_EVENT_VNET_RESET,
|
||||
};
|
||||
|
||||
enum crete_portchange_event_subtype {
|
||||
CRETE_EVENT_PORT_LINK_DOWN = 0,
|
||||
CRETE_EVENT_PORT_LINK_UP = 1,
|
||||
CRETE_EVENT_PORT_LINK_ERR
|
||||
};
|
||||
|
||||
enum crete_cp_event_subtype {
|
||||
CRETE_EVENT_STYPE_CMDPATH = 0,
|
||||
CRETE_EVENT_STYPE_ADMIN = 1,
|
||||
};
|
||||
|
||||
struct crete_event_irq {
|
||||
struct atomic_notifier_head nh[CRETE_EVENT_TYPE_MAX];
|
||||
cpumask_var_t mask;
|
||||
char name[CRETE_MAX_IRQ_NAME];
|
||||
u32 vector;
|
||||
u16 entry;
|
||||
void *event_buf;
|
||||
dma_addr_t event_dma;
|
||||
u8 event_buf_size;
|
||||
};
|
||||
|
||||
struct crete_event_cmd {
|
||||
uint16_t entry_id;
|
||||
uint16_t rsvd;
|
||||
};
|
||||
|
||||
struct crete_event_buffer_head {
|
||||
u8 resv0;
|
||||
u8 event_seq;
|
||||
uint8_t event_sig;
|
||||
uint8_t event_entry_length;
|
||||
};
|
||||
|
||||
|
||||
struct crete_event_entry {
|
||||
uint8_t event_length;
|
||||
uint8_t event_sub_type;
|
||||
uint16_t event_type;
|
||||
uint32_t event_data[]; //mlx5_eqe
|
||||
};
|
||||
|
||||
struct crete_nb {
|
||||
struct notifier_block nb;
|
||||
u16 event_type;
|
||||
};
|
||||
|
||||
#define CRETE_NB_INIT(name, handler, event) do { \
|
||||
(name)->nb.notifier_call = handler; \
|
||||
(name)->event_type = CRETE_EVENT_TYPE_##event; \
|
||||
} while (0)
|
||||
|
||||
#define crete_nb_cof(ptr, type, member) \
|
||||
(container_of(container_of(ptr, struct crete_nb, nb), type, member))
|
||||
|
||||
extern int crete_event_notifier_register(struct crete_core_dev *dev, struct crete_nb *nb);
|
||||
extern int crete_event_notifier_unregister(struct crete_core_dev *dev, struct crete_nb *nb);
|
||||
|
||||
#endif
|
@ -0,0 +1,515 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "crete.h"
|
||||
#include "crete_cmd.h"
|
||||
#include "crete_regs.h"
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/uuid.h>
|
||||
#include "crete_fw_update.h"
|
||||
#include "crete_pldmfw_lib.h"
|
||||
#include "crete_cmd_if.h"
|
||||
|
||||
|
||||
static const struct pldmfw_ops crete_fwu_ops = {
|
||||
.match_record = NULL,
|
||||
.send_package_data = NULL,
|
||||
.send_component_table = NULL,
|
||||
.flash_component = NULL,
|
||||
.finalize_update = NULL,
|
||||
};
|
||||
|
||||
static void crete_fwu_status_notify(struct crete_fwu_priv *fwu_priv,
|
||||
const char *msg, const char *comp_name,
|
||||
u32 done_bytes, u32 total_bytes)
|
||||
{
|
||||
devlink_flash_update_status_notify(fwu_priv->devlink, msg, comp_name,
|
||||
done_bytes, total_bytes);
|
||||
}
|
||||
|
||||
static int crete_acquire_flashlock(struct crete_fwu_priv *fwu_priv)
|
||||
{
|
||||
u32 in[CRETE_ST_SZ_DW(fwu_lock_in)] = {0};
|
||||
u32 out[CRETE_ST_SZ_DW(fwu_lock_out)] = {0};
|
||||
u16 seq_id = fwu_priv->seq_id;
|
||||
int ret = 0;
|
||||
u8 st = 0;
|
||||
|
||||
CRETE_SET(fwu_lock_in, in, cmd_id, CRETE_CMD_FWU_LOCK);
|
||||
CRETE_SET(fwu_lock_in, in, seq_id, seq_id);
|
||||
CRETE_SET(fwu_lock_in, in, cmd, CRETE_FWU_LOCKED);
|
||||
|
||||
ret = crete_cmd_exec_polling(fwu_priv->cdev, in, sizeof(in), out, sizeof(out));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
st = CRETE_GET(fwu_lock_out, out, status);
|
||||
ret = CRETE_GET16(fwu_lock_out, out, status_inner);
|
||||
cretefw_info(fwu_priv, "st[%d] fwlock inner status[%d]\n", st, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int crete_release_flashlock(struct crete_fwu_priv *fwu_priv)
|
||||
{
|
||||
u32 in[CRETE_ST_SZ_DW(fwu_unlock_in)] = {0};
|
||||
u32 out[CRETE_ST_SZ_DW(fwu_unlock_out)] = {0};
|
||||
u16 seq_id = fwu_priv->seq_id;
|
||||
int ret = 0;
|
||||
u8 st = 0;
|
||||
|
||||
CRETE_SET(fwu_unlock_in, in, cmd_id, CRETE_CMD_FWU_UNLOCK);
|
||||
CRETE_SET(fwu_unlock_in, in, seq_id, seq_id);
|
||||
CRETE_SET(fwu_unlock_in, in, cmd, CRETE_FWU_UNLOCK);
|
||||
|
||||
ret = crete_cmd_exec_polling(fwu_priv->cdev, in, sizeof(in), out, sizeof(out));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
st = CRETE_GET(fwu_unlock_out, out, status);
|
||||
ret = CRETE_GET16(fwu_unlock_out, out, status_inner);
|
||||
cretefw_info(fwu_priv, "st[%d] fwu unlock inner status[%d]\n", st, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int crete_fwu_pkey(struct crete_fwu_priv *fwu_priv, struct crete_pldmfw_priv *data)
|
||||
{
|
||||
u32 in[CRETE_ST_SZ_DW(fwu_pkey_in)] = {0};
|
||||
u32 out[CRETE_ST_SZ_DW(fwu_pkey_out)] = {0};
|
||||
u16 seq_id = fwu_priv->seq_id;
|
||||
int ret = 0;
|
||||
u8 st = 0;
|
||||
|
||||
CRETE_SET(fwu_pkey_in, in, cmd_id, CRETE_CMD_FWU_PKEY);
|
||||
CRETE_SET(fwu_pkey_in, in, seq_id, seq_id);
|
||||
CRETE_SET(fwu_pkey_in, in, cmd, CRETE_FWU_PKEY);
|
||||
|
||||
ret = crete_cmd_exec_polling(fwu_priv->cdev, in, sizeof(in), out, sizeof(out));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
st = CRETE_GET(fwu_pkey_out, out, status);
|
||||
ret = CRETE_GET16(fwu_pkey_out, out, status_inner);
|
||||
cretefw_info(fwu_priv, "st[%d] fwu pkey inner status[%d]\n", st, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int crete_fwu_ver(struct crete_fwu_priv *fwu_priv, struct crete_pldmfw_priv *data)
|
||||
{
|
||||
u32 *in, *out;
|
||||
int outlen = CRETE_ST_SZ_BYTES(fwu_ver_out);
|
||||
int inlen = CRETE_ST_SZ_BYTES(fwu_ver_in);
|
||||
u16 seq_id = fwu_priv->seq_id;
|
||||
int ret = 0;
|
||||
u8 st = 0;
|
||||
int component_count = data->component_count;
|
||||
struct pldmfw_component *component;
|
||||
int i = 0;
|
||||
|
||||
inlen += component_count * CRETE_FLD_SZ_BYTES(fwu_ver_in, comp_list[0]);
|
||||
outlen += component_count * CRETE_FLD_SZ_BYTES(fwu_ver_out, version_list[0]);
|
||||
in = kvzalloc(inlen, GFP_KERNEL);
|
||||
out = kvzalloc(outlen, GFP_KERNEL);
|
||||
if (!out || !in) {
|
||||
ret = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
CRETE_SET(fwu_ver_in, in, cmd_id, CRETE_CMD_FWU_VER);
|
||||
CRETE_SET(fwu_ver_in, in, cmd, CRETE_FWU_VER);
|
||||
CRETE_SET(fwu_ver_in, in, seq_id, seq_id);
|
||||
|
||||
list_for_each_entry(component, &data->components, entry) {
|
||||
if (i >= component_count)
|
||||
break;
|
||||
|
||||
CRETE_ARRAY_SET(fwu_ver_in, in, comp_list, i, component->identifier);
|
||||
i++;
|
||||
}
|
||||
|
||||
ret = crete_cmd_exec_polling(fwu_priv->cdev, in, inlen, out, outlen);
|
||||
if (ret < 0)
|
||||
goto err_out;
|
||||
|
||||
st = CRETE_GET(fwu_ver_out, out, status);
|
||||
ret = CRETE_GET(fwu_ver_out, out, status_inner);
|
||||
cretefw_info(fwu_priv, "st[%d] fwu_ver inner status[%d]\n", st, ret);
|
||||
|
||||
/*TODO*/
|
||||
/*
|
||||
* version_out = CRETE_ADDR_OF(fwu_ver_out, out, version_list);
|
||||
* for (i = 0; i < component_count; i++, version_out += CRETE_ST_SZ_BYTES(version_list)) {
|
||||
* version = CRETE_GET_PR(version_list, version_out, qid);
|
||||
* version_efuse = CRETE_GET_PR(version_list, version_out, result);
|
||||
* crete_fw_checkversion(version, version_efuse, flag);
|
||||
* }
|
||||
*/
|
||||
|
||||
err_out:
|
||||
kvfree(in);
|
||||
kvfree(out);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
crete_check_fwu_ack(struct crete_fwu_priv *fwu_priv, const char *comp_name, u16 status_code,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
#define CRETEFW_ACK_PRFX "check fwu_ack: "
|
||||
#define CRETEFW_CHECK_ACK(msg, err) \
|
||||
CRETEFW_ERR_MSG(fwu_priv, extack, CRETEFW_ACK_PRFX msg, err)
|
||||
|
||||
cretefw_info(fwu_priv, "%s: firmware response code 0x%x\n", comp_name, status_code);
|
||||
|
||||
switch (status_code) {
|
||||
case CRETE_FWU_SUCCESS:
|
||||
/* firmware indicated this update is good to proceed */
|
||||
return;
|
||||
case CRETE_FWU_ERR_SEQ_ID:
|
||||
CRETEFW_CHECK_ACK("flash components err seq_id", status_code);
|
||||
break;
|
||||
case CRETE_FWU_CRC_ERR:
|
||||
CRETEFW_CHECK_ACK("flash components crc err", status_code);
|
||||
break;
|
||||
case CRETE_FWU_BUSY:
|
||||
CRETEFW_CHECK_ACK("flash device is busy", status_code);
|
||||
break;
|
||||
case CRETE_FWU_LOCK_FAIL:
|
||||
CRETEFW_CHECK_ACK("flash lock failed", status_code);
|
||||
break;
|
||||
case CRETE_FWU_PKEY_ERR:
|
||||
CRETEFW_CHECK_ACK("flash components pkey err", status_code);
|
||||
break;
|
||||
case CRETE_FWU_INVALID_ID:
|
||||
CRETEFW_CHECK_ACK("flash components invalid img id", status_code);
|
||||
break;
|
||||
case CRETE_FWU_FLASH_ERR:
|
||||
CRETEFW_CHECK_ACK("flash components write err", status_code);
|
||||
break;
|
||||
case CRETE_FWU_EFUSE_ERR:
|
||||
CRETEFW_CHECK_ACK("flash components write efuse err", status_code);
|
||||
break;
|
||||
case CRETE_FWU_SYNC_ERR:
|
||||
CRETEFW_CHECK_ACK("flash components sync err", status_code);
|
||||
break;
|
||||
case CRETE_FWU_TRANS_ERR:
|
||||
CRETEFW_CHECK_ACK("flash components trans err", status_code);
|
||||
break;
|
||||
case CRETE_FWU_TIMEOUT:
|
||||
CRETEFW_CHECK_ACK("flash components wait timeout", status_code);
|
||||
break;
|
||||
case CRETE_FWU_STATUS_ERR:
|
||||
CRETEFW_CHECK_ACK("flash components status mismatch", status_code);
|
||||
break;
|
||||
case CRETE_FWU_OTHER_ERR:
|
||||
CRETEFW_CHECK_ACK("flash components unexpected err", status_code);
|
||||
break;
|
||||
default:
|
||||
CRETEFW_CHECK_ACK("Unrecognized command status code", status_code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int crete_fwu_end(struct crete_fwu_priv *fwu_priv, struct crete_pldmfw_priv *data)
|
||||
{
|
||||
u32 in[CRETE_ST_SZ_DW(fwu_end_in)] = {0};
|
||||
u32 out[CRETE_ST_SZ_DW(fwu_end_out)] = {0};
|
||||
u16 seq_id = fwu_priv->seq_id;
|
||||
int ret = 0;
|
||||
u8 st = 0;
|
||||
|
||||
CRETE_SET(fwu_end_in, in, cmd_id, CRETE_CMD_FWU_END);
|
||||
CRETE_SET(fwu_end_in, in, cmd, CRETE_FWU_IMG_END);
|
||||
CRETE_SET(fwu_end_in, in, seq_id, seq_id);
|
||||
|
||||
ret = crete_cmd_exec_polling(fwu_priv->cdev, in, sizeof(in), out, sizeof(out));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
st = CRETE_GET(fwu_end_out, out, status);
|
||||
ret = CRETE_GET(fwu_end_out, out, status_inner);
|
||||
cretefw_info(fwu_priv, "st[%d] fwu end inner end [%d]\n", st, ret);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static int crete_flash_component_block(u32 offset_uint, u16 block_size, u8 *block,
|
||||
bool last_cmd, u16 identifier, struct crete_fwu_priv *fwu_priv, u16 *st_code)
|
||||
{
|
||||
u32 out[CRETE_ST_SZ_DW(fwu_xfer_out)] = {0};
|
||||
u32 *in, *block_ptr;
|
||||
int inlen = CRETE_ST_SZ_BYTES(fwu_xfer_in);
|
||||
u32 calculated_crc = 0;
|
||||
u16 seq_id = fwu_priv->seq_id;
|
||||
int ret = 0;
|
||||
u8 st = 0;
|
||||
int attempts = 0;
|
||||
|
||||
inlen += block_size;
|
||||
in = kvzalloc(inlen, GFP_KERNEL);
|
||||
if (!in) {
|
||||
ret = -ENOMEM;
|
||||
goto flash_out;
|
||||
}
|
||||
|
||||
identifier = last_cmd ? (identifier | BIT(15)) : (identifier & ~BIT(15));
|
||||
CRETE_SET(fwu_xfer_in, in, cmd_id, CRETE_CMD_FWU_XFER);
|
||||
CRETE_SET(fwu_xfer_in, in, seq_id, seq_id);
|
||||
CRETE_SET(fwu_xfer_in, in, cmd, CRETE_FWU_IMG_XFER);
|
||||
CRETE_SET(fwu_xfer_in, in, flag, identifier);
|
||||
CRETE_SET(fwu_xfer_in, in, len, block_size);
|
||||
CRETE_SET(fwu_xfer_in, in, offset, offset_uint);
|
||||
|
||||
block_ptr = CRETE_ADDR_OF(fwu_xfer_in, in, data);
|
||||
memcpy(block_ptr, block, block_size);
|
||||
|
||||
calculated_crc = crc32_le(~0, block, block_size) ^ ~0;
|
||||
CRETE_SET(fwu_xfer_in, in, crc, calculated_crc);
|
||||
|
||||
do {
|
||||
ret = crete_cmd_exec_polling(fwu_priv->cdev, in, inlen, out, sizeof(out));
|
||||
if (ret && ret != -EREMOTEIO) {
|
||||
cretefw_err(fwu_priv, "fwu_xfer cmd carryout failed ret[%d]\n", ret);
|
||||
goto flash_out;
|
||||
}
|
||||
st = CRETE_GET(fwu_xfer_out, out, status);
|
||||
*st_code = CRETE_GET(fwu_xfer_out, out, status_inner);
|
||||
|
||||
cretefw_info(fwu_priv, "attempts[%d] st[%d] fwu_xfer status[%d]\n",
|
||||
attempts, st, *st_code);
|
||||
|
||||
if (!st && *st_code == CRETE_FWU_SUCCESS)
|
||||
goto flash_out;
|
||||
|
||||
if (*st_code != CRETE_FWU_CRC_ERR)
|
||||
goto flash_out;
|
||||
|
||||
attempts++;
|
||||
} while (attempts < CRETE_MAX_ATTEMPTS_XFER);
|
||||
|
||||
flash_out:
|
||||
kvfree(in);
|
||||
return ret ? ret : *st_code;
|
||||
}
|
||||
|
||||
static int crete_flash_component(struct crete_fwu_priv *fwu_priv,
|
||||
struct pldmfw_component *component)
|
||||
{
|
||||
u32 offset = 0;
|
||||
u32 offset_uint = 0;
|
||||
bool last_cmd;
|
||||
u16 status_code;
|
||||
int err;
|
||||
struct netlink_ext_ack *extack = fwu_priv->extack;
|
||||
u8 *block;
|
||||
const u8 *image = component->component_data;
|
||||
u32 length = component->component_size;
|
||||
const char *comp_name = component->version_string;
|
||||
|
||||
if (comp_name == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
cretefw_info(fwu_priv, "Beginning write of flash component '%s' size '%d'\n",
|
||||
comp_name, length);
|
||||
crete_fwu_status_notify(fwu_priv, "Flashing component", comp_name, 0, length);
|
||||
|
||||
block = kzalloc(CRETE_MAX_FWU_BUF_LEN, GFP_KERNEL);
|
||||
if (!block)
|
||||
return -ENOMEM;
|
||||
|
||||
do {
|
||||
u32 block_size;
|
||||
|
||||
block_size = min_t(u32, CRETE_MAX_FWU_BUF_LEN, length - offset);
|
||||
last_cmd = !(offset + block_size < length);
|
||||
memcpy(block, image + offset, block_size);
|
||||
status_code = CRETE_FWU_OTHER_ERR;
|
||||
err = crete_flash_component_block(offset_uint, block_size, block,
|
||||
last_cmd, component->identifier, fwu_priv, &status_code);
|
||||
if (err)
|
||||
break;
|
||||
|
||||
offset += block_size;
|
||||
fwu_priv->seq_id++;
|
||||
CRETE_FWU_INCREMENT_OFFSET(offset_uint);
|
||||
crete_fwu_status_notify(fwu_priv, "Flashing component", comp_name, offset, length);
|
||||
} while (!last_cmd);
|
||||
|
||||
crete_check_fwu_ack(fwu_priv, comp_name, status_code, extack);
|
||||
|
||||
if (err)
|
||||
crete_fwu_status_notify(fwu_priv, "Flashing failed",
|
||||
comp_name, length, length);
|
||||
else
|
||||
crete_fwu_status_notify(fwu_priv, "Flashing done",
|
||||
comp_name, length, length);
|
||||
|
||||
kfree(block);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int crete_flash_components(struct crete_fwu_priv *fwu_priv, struct crete_pldmfw_priv *data)
|
||||
{
|
||||
struct pldmfw_record *record;
|
||||
struct pldmfw_component *component;
|
||||
unsigned long *bitmap = NULL;
|
||||
int err = 0;
|
||||
|
||||
list_for_each_entry(record, &data->records, entry) {
|
||||
bitmap = record->component_bitmap;
|
||||
list_for_each_entry(component, &data->components, entry) {
|
||||
u8 index = component->index, transfer_flag = 0;
|
||||
|
||||
if (!test_bit(index, bitmap))
|
||||
continue;
|
||||
cretefw_info(fwu_priv, "identifier: %d\n", component->identifier);
|
||||
cretefw_info(fwu_priv, "version_string: %s\n", component->version_string);
|
||||
cretefw_info(fwu_priv, "classification: %d\n", component->classification);
|
||||
|
||||
if(component->version_string == NULL)
|
||||
continue;
|
||||
|
||||
/* determine whether this is the start, middle, end, or both
|
||||
* the start and end of the component tables
|
||||
*/
|
||||
if (index == find_first_bit(bitmap, data->component_bitmap_len))
|
||||
transfer_flag |= PLDM_TRANSFER_FLAG_START;
|
||||
if (index == find_last_bit(bitmap, data->component_bitmap_len))
|
||||
transfer_flag |= PLDM_TRANSFER_FLAG_END;
|
||||
if (!transfer_flag)
|
||||
transfer_flag = PLDM_TRANSFER_FLAG_MIDDLE;
|
||||
err = crete_flash_component(fwu_priv, component);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int crete_flash_image(struct crete_fwu_priv *fwu_priv, const struct firmware *fw)
|
||||
{
|
||||
struct crete_pldmfw_priv *data;
|
||||
int err;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_LIST_HEAD(&data->records);
|
||||
INIT_LIST_HEAD(&data->components);
|
||||
|
||||
data->fw = fw;
|
||||
data->context = &fwu_priv->context;
|
||||
|
||||
err = crete_pldm_parse_image(data);
|
||||
if (err)
|
||||
goto out_release_data;
|
||||
|
||||
cretefw_info(fwu_priv, "total_header_size : %d\n", data->total_header_size);
|
||||
cretefw_info(fwu_priv, "record_count : %d\n", data->record_count);
|
||||
cretefw_info(fwu_priv, "component_bitmap_len : %d\n", data->component_bitmap_len);
|
||||
cretefw_info(fwu_priv, "component_count : %d\n", data->component_count);
|
||||
|
||||
err = crete_fwu_pkey(fwu_priv, data);
|
||||
if (err)
|
||||
goto out_release_data;
|
||||
|
||||
err = crete_fwu_ver(fwu_priv, data);
|
||||
if (err)
|
||||
goto out_release_data;
|
||||
|
||||
err = crete_flash_components(fwu_priv, data);
|
||||
if (err)
|
||||
goto out_release_data;
|
||||
|
||||
err = crete_fwu_end(fwu_priv, data);
|
||||
|
||||
out_release_data:
|
||||
crete_pldmfw_free_priv(data);
|
||||
kfree(data);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int crete_firmware_flash(struct crete_core_dev *cdev,
|
||||
const struct firmware *firmware,
|
||||
struct netlink_ext_ack *extack, enum crete_fwu_type type)
|
||||
{
|
||||
struct crete_fwu_priv fwu_priv;
|
||||
int err;
|
||||
|
||||
if (!crete_core_is_pf(cdev))
|
||||
return 0;
|
||||
|
||||
memset(&fwu_priv, 0, sizeof(fwu_priv));
|
||||
fwu_priv.context.ops = &crete_fwu_ops;
|
||||
fwu_priv.context.dev = cdev->device;
|
||||
fwu_priv.devlink = priv_to_devlink(cdev);
|
||||
fwu_priv.extack = extack;
|
||||
fwu_priv.seq_id = 0;
|
||||
fwu_priv.cdev = cdev;
|
||||
|
||||
cretefw_info(&fwu_priv, "Initialize firmware flash process\n");
|
||||
#ifndef CONFIG_DEVLINK_CARRYOUT_OPTIMIZE
|
||||
if (type == CRETE_FWU_DEVLINK)
|
||||
devlink_flash_update_begin_notify(fwu_priv.devlink);
|
||||
#endif
|
||||
crete_fwu_status_notify(&fwu_priv, "Preparing to flash", NULL, 0, 0);
|
||||
|
||||
err = crete_acquire_flashlock(&fwu_priv);
|
||||
if (err) {
|
||||
CRETEFW_ERR_MSG(&fwu_priv, extack, "Failed to acquire device flash lock", err);
|
||||
goto flash_out;
|
||||
}
|
||||
|
||||
err = crete_flash_image(&fwu_priv, firmware);
|
||||
if (err)
|
||||
CRETEFW_ERR_MSG(&fwu_priv, extack, "Failed to flash PLDM image", err);
|
||||
|
||||
err = crete_release_flashlock(&fwu_priv);
|
||||
if (err)
|
||||
CRETEFW_ERR_MSG(&fwu_priv, extack, "Failed to release device flash lock", err);
|
||||
|
||||
flash_out:
|
||||
#ifndef CONFIG_DEVLINK_CARRYOUT_OPTIMIZE
|
||||
if (type == CRETE_FWU_DEVLINK)
|
||||
devlink_flash_update_end_notify(fwu_priv.devlink);
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(crete_firmware_flash);
|
||||
|
||||
|
@ -0,0 +1,129 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _CRETE_FW_UPDATE_H
|
||||
#define _CRETE_FW_UPDATE_H
|
||||
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/pldmfw.h>
|
||||
#include <linux/firmware.h>
|
||||
|
||||
#define CRETE_MAX_FWU_BUF_LEN 512
|
||||
#define CRETE_MAX_FWU_BUF_LEN_UINT 256
|
||||
#define CRETE_FWU_OFFSET_INCREMENT (CRETE_MAX_FWU_BUF_LEN / CRETE_MAX_FWU_BUF_LEN_UINT)
|
||||
#define CRETE_FWU_INCREMENT_OFFSET(offset) ((offset) += CRETE_FWU_OFFSET_INCREMENT)
|
||||
#define CRETE_MAX_ATTEMPTS_XFER 3
|
||||
|
||||
#define CRETE_FWU_PKEY_FLAG BIT(1)
|
||||
#define CRETE_FWU_ACTIVE_FLAG BIT(2)
|
||||
#define CRETE_FWU_FORCE_FLAG BIT(3)
|
||||
#define CRETE_FWU_EFUSE_FLAH BIT(4)
|
||||
|
||||
|
||||
enum crete_fwu_cmd {
|
||||
CRETE_FWU_LOCKED = 1,
|
||||
CRETE_FWU_PKEY,
|
||||
CRETE_FWU_VER,
|
||||
CRETE_FWU_IMG_XFER,
|
||||
CRETE_FWU_IMG_END,
|
||||
CRETE_FWU_ACT,
|
||||
CRETE_FWU_SYNC,
|
||||
CRETE_FWU_EFUSE,
|
||||
CRETE_FWU_UNLOCK,
|
||||
CRETE_FWU_QUERY,
|
||||
CRETE_FWU_LOG,
|
||||
CRETE_FWU_IMG_INFO,
|
||||
CRETE_FWU_IMG_READ,
|
||||
CRETE_FWU_ACK_HALF = 0xfe,
|
||||
CRETE_FWU_ACK = 0xff,
|
||||
};
|
||||
|
||||
enum crete_fwu_ack {
|
||||
CRETE_FWU_SUCCESS = 0,
|
||||
CRETE_FWU_ERR_SEQ_ID,
|
||||
CRETE_FWU_CRC_ERR,
|
||||
CRETE_FWU_BUSY,
|
||||
CRETE_FWU_LOCK_FAIL,
|
||||
CRETE_FWU_PKEY_ERR,
|
||||
CRETE_FWU_INVALID_ID,
|
||||
CRETE_FWU_FLASH_ERR,
|
||||
CRETE_FWU_EFUSE_ERR,
|
||||
CRETE_FWU_SYNC_ERR,
|
||||
CRETE_FWU_TRANS_ERR,
|
||||
CRETE_FWU_TIMEOUT,
|
||||
CRETE_FWU_STATUS_ERR,
|
||||
CRETE_FWU_OTHER_ERR,
|
||||
};
|
||||
|
||||
enum crete_fwu_type {
|
||||
CRETE_FWU_ETHTOOL = 0,
|
||||
CRETE_FWU_DEVLINK = 1,
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct crete_fwu_priv {
|
||||
struct pldmfw context;
|
||||
struct devlink *devlink;
|
||||
struct crete_core_dev *cdev;
|
||||
struct netlink_ext_ack *extack;
|
||||
u16 seq_id;
|
||||
};
|
||||
|
||||
static inline
|
||||
struct device *cretefw_dev_dev(struct crete_fwu_priv *fwu_priv)
|
||||
{
|
||||
return fwu_priv->cdev->device;
|
||||
}
|
||||
|
||||
#define CRETEFW_PRFX "cretefw: "
|
||||
|
||||
#define cretefw_info(fwu_priv, fmt, ...) \
|
||||
dev_info(cretefw_dev_dev(fwu_priv), CRETEFW_PRFX fmt, ## __VA_ARGS__)
|
||||
#define cretefw_err(fwu_priv, fmt, ...) \
|
||||
dev_err(cretefw_dev_dev(fwu_priv), CRETEFW_PRFX fmt, ## __VA_ARGS__)
|
||||
#define cretefw_dbg(fwu_priv, fmt, ...) \
|
||||
dev_dbg(cretefw_dev_dev(fwu_priv), CRETEFW_PRFX fmt, ## __VA_ARGS__)
|
||||
|
||||
#define CRETEFW_ERR_PRFX "Firmware flash failed: "
|
||||
#define CRETEFW_ERR_MSG(fwu_priv, extack, msg, err) do { \
|
||||
cretefw_err(fwu_priv, "%s, err (%d)\n", CRETEFW_ERR_PRFX msg, err); \
|
||||
NL_SET_ERR_MSG_MOD(extack, CRETEFW_ERR_PRFX msg); \
|
||||
} while (0)
|
||||
|
||||
int crete_firmware_flash(struct crete_core_dev *cdev,
|
||||
const struct firmware *firmware,
|
||||
struct netlink_ext_ack *extack, enum crete_fwu_type type);
|
||||
|
||||
|
||||
#endif
|
@ -0,0 +1,840 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#include <linux/netdevice.h>
|
||||
#include <net/bonding.h>
|
||||
#include "crete.h"
|
||||
#include "crete_cmd.h"
|
||||
#include "crete_cmd_if.h"
|
||||
|
||||
static inline bool crete_lag_is_supported(struct crete_core_dev *dev)
|
||||
{
|
||||
if (!dev->lag_cap.lag_master) {
|
||||
if (dev->lag_cap.num_ports == CRETE_MIN_LAG_PORTS ||
|
||||
dev->lag_cap.num_ports <= CRETE_MAX_LAG_PORTS)
|
||||
dev->lag_enable = CRETE_LAG_DISABLE;
|
||||
|
||||
return false;
|
||||
} else {
|
||||
if (dev->lag_cap.num_ports != CRETE_MIN_LAG_PORTS &&
|
||||
dev->lag_cap.num_ports != CRETE_MAX_LAG_PORTS) {
|
||||
|
||||
dev->lag_enable = CRETE_LAG_DISABLE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void crete_ldev_get(struct crete_lag *ldev)
|
||||
{
|
||||
kref_get(&ldev->ref);
|
||||
}
|
||||
|
||||
static void crete_ldev_free(struct kref *ref)
|
||||
{
|
||||
struct crete_lag *ldev = container_of(ref, struct crete_lag, ref);
|
||||
|
||||
if (ldev->nb.notifier_call)
|
||||
unregister_netdevice_notifier_net(&init_net, &ldev->nb);
|
||||
|
||||
destroy_workqueue(ldev->wq);
|
||||
mutex_destroy(&ldev->lock);
|
||||
kfree(ldev);
|
||||
}
|
||||
|
||||
static void crete_ldev_put(struct crete_lag *ldev)
|
||||
{
|
||||
kref_put(&ldev->ref, crete_ldev_free);
|
||||
}
|
||||
|
||||
static void *pci_get_other_drvdata(struct device *this, struct device *other)
|
||||
{
|
||||
if (this->driver != other->driver)
|
||||
return NULL;
|
||||
|
||||
return pci_get_drvdata(to_pci_dev(other));
|
||||
}
|
||||
|
||||
static int _next_phys_dev(struct crete_core_dev *tmp_dev,
|
||||
const struct crete_core_dev *curr_dev)
|
||||
{
|
||||
|
||||
if (tmp_dev == curr_dev)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool crete_check_in_one_lag(struct crete_core_dev *t, struct crete_core_dev *tmp)
|
||||
{
|
||||
if (t->lag_cap.lag_id != tmp->lag_cap.lag_id ||
|
||||
t->lag_cap.mode_support != tmp->lag_cap.mode_support ||
|
||||
t->lag_cap.hash_type != tmp->lag_cap.hash_type ||
|
||||
t->lag_cap.num_ports != tmp->lag_cap.num_ports)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* should be implemented in the public interface
|
||||
*/
|
||||
static int next_phys_lag_dev(struct device *dev, const void *data)
|
||||
{
|
||||
struct crete_core_dev *tmp_dev, *this = (struct crete_core_dev *)data;
|
||||
|
||||
tmp_dev = pci_get_other_drvdata(this->device, dev);
|
||||
if (!tmp_dev)
|
||||
goto done;
|
||||
|
||||
if (!crete_core_is_pf(tmp_dev))
|
||||
goto done;
|
||||
|
||||
if (!crete_lag_is_supported(tmp_dev))
|
||||
goto done;
|
||||
|
||||
if (!crete_check_in_one_lag(this, tmp_dev))
|
||||
goto done;
|
||||
|
||||
return _next_phys_dev(tmp_dev, data);
|
||||
done:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* should be implemented in the public interface
|
||||
*/
|
||||
static struct crete_core_dev *crete_get_next_dev(struct crete_core_dev *dev,
|
||||
int (*match)(struct device *dev, const void *data))
|
||||
{
|
||||
struct device *next;
|
||||
|
||||
if (!crete_core_is_pf(dev))
|
||||
return NULL;
|
||||
|
||||
next = bus_find_device(&pci_bus_type, NULL, dev, match);
|
||||
if (!next)
|
||||
return NULL;
|
||||
|
||||
put_device(next);
|
||||
|
||||
return pci_get_drvdata(to_pci_dev(next));
|
||||
}
|
||||
|
||||
/*
|
||||
* should be implemented in the public interface
|
||||
*/
|
||||
struct crete_core_dev *crete_get_next_phy_dev_lag(struct crete_core_dev *dev)
|
||||
{
|
||||
return crete_get_next_dev(dev, &next_phys_lag_dev);
|
||||
}
|
||||
|
||||
static void crete_queue_bond_work(struct crete_lag *ldev, unsigned long delay)
|
||||
{
|
||||
queue_delayed_work(ldev->wq, &ldev->bond_work, delay);
|
||||
}
|
||||
|
||||
struct crete_cmd_lag_context_bits test;
|
||||
|
||||
static int crete_cmd_create_lag(struct crete_lag *ldev)
|
||||
{
|
||||
int in_len = CRETE_ST_SZ_BYTES(create_lag_in);
|
||||
int out_len = CRETE_ST_SZ_BYTES(create_lag_out);
|
||||
void *in, *out, *lagc;
|
||||
int lagc_size = CRETE_ST_SZ_BYTES(lag_context);
|
||||
struct crete_core_dev *dev = ldev->pf[CRETE_LAG_P1].dev;
|
||||
int status;
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
|
||||
in_len += lagc_size;
|
||||
|
||||
in = kvzalloc(in_len, GFP_KERNEL);
|
||||
if (!in) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
out = kvzalloc(out_len, GFP_KERNEL);
|
||||
if (!out) {
|
||||
ret = -ENOMEM;
|
||||
kvfree(in);
|
||||
goto done;
|
||||
}
|
||||
|
||||
CRETE_SET(create_lag_in, in, cmd_id, CRETE_CMD_LAG_CONFIG);
|
||||
CRETE_SET(create_lag_in, in, opcode, CRETE_CREATE_LAG);
|
||||
lagc = CRETE_ADDR_OF(create_lag_in, in, lag_context);
|
||||
|
||||
CRETE_SET(lag_context, lagc, lag_id, dev->lag_cap.lag_id);
|
||||
CRETE_SET(lag_context, lagc, lag_mode, ldev->info.upper_lag_mode);
|
||||
CRETE_SET(lag_context, lagc, hash_type, ldev->info.hash_type);
|
||||
CRETE_SET(lag_context, lagc, lu_te_num, ldev->ports);
|
||||
|
||||
for (i = 0; i < ldev->ports; i++)
|
||||
CRETE_ARRAY_SET(lag_context, lagc, lu_te_mem, i, ldev->pf[i].dev->sfi_id);
|
||||
|
||||
ret = crete_cmd_exec_polling(dev, in, in_len, out, sizeof(out));
|
||||
if (ret) {
|
||||
crete_info(dev->device, "create lag cmd err[%d]", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
status = CRETE_GET(create_lag_out, out, status);
|
||||
crete_info(dev->device, "create lag status:%d", status);
|
||||
|
||||
out:
|
||||
kfree(in);
|
||||
kfree(out);
|
||||
done:
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static void crete_activate_lag(struct crete_lag *ldev)
|
||||
{
|
||||
crete_cmd_create_lag(ldev);
|
||||
ldev->mode = CRETE_LAG_ACTIVE;
|
||||
}
|
||||
|
||||
static int crete_cmd_modify_lag(struct crete_lag *ldev)
|
||||
{
|
||||
int in_len = CRETE_ST_SZ_BYTES(modify_lag_in);
|
||||
int out_len = CRETE_ST_SZ_BYTES(modify_lag_out);
|
||||
void *in, *out, *lagc;
|
||||
int lagc_size = CRETE_ST_SZ_BYTES(lag_context);
|
||||
struct crete_core_dev *dev = ldev->pf[CRETE_LAG_P1].dev;
|
||||
int status;
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
|
||||
in_len += lagc_size;
|
||||
|
||||
in = kvzalloc(in_len, GFP_KERNEL);
|
||||
if (!in) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
out = kvzalloc(out_len, GFP_KERNEL);
|
||||
if (!out) {
|
||||
ret = -ENOMEM;
|
||||
kvfree(in);
|
||||
goto done;
|
||||
}
|
||||
|
||||
CRETE_SET(modify_lag_in, in, cmd_id, CRETE_CMD_LAG_CONFIG);
|
||||
CRETE_SET(modify_lag_in, in, opcode, CRETE_MODIFY_LAG);
|
||||
lagc = CRETE_ADDR_OF(modify_lag_in, in, lag_context);
|
||||
|
||||
CRETE_SET(lag_context, lagc, lag_id, dev->lag_cap.lag_id);
|
||||
CRETE_SET(lag_context, lagc, lag_mode, ldev->info.upper_lag_mode);
|
||||
CRETE_SET(lag_context, lagc, hash_type, dev->lag_cap.hash_type);
|
||||
|
||||
for (i = 0; i < ldev->ports; i++) {
|
||||
if (ldev->info.netdev_state[i].link_up &
|
||||
ldev->info.netdev_state[i].tx_enabled) {
|
||||
CRETE_ARRAY_SET(lag_context, lagc, lu_te_mem, ldev->info.netdev_idx,
|
||||
ldev->pf[i].dev->sfi_id);
|
||||
ldev->info.netdev_idx++;
|
||||
pr_debug("func:%s--line:%d sfi_id:0x%x\n", __func__, __LINE__, ldev->pf[i].dev->sfi_id);
|
||||
}
|
||||
}
|
||||
|
||||
ldev->info.active_port = ldev->info.netdev_idx;
|
||||
ldev->info.netdev_idx = 0;
|
||||
|
||||
CRETE_SET(lag_context, lagc, lu_te_num, ldev->info.active_port);
|
||||
|
||||
ret = crete_cmd_exec_polling(dev, in, in_len, out, sizeof(out));
|
||||
if (ret) {
|
||||
crete_info(dev->device, "modify lag cmd err[%d]", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
status = CRETE_GET(modify_lag_out, out, status);
|
||||
crete_info(dev->device, "modify lag status:%d", status);
|
||||
|
||||
out:
|
||||
kfree(in);
|
||||
kfree(out);
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void crete_modify_lag(struct crete_lag *ldev)
|
||||
{
|
||||
crete_cmd_modify_lag(ldev);
|
||||
}
|
||||
|
||||
static int crete_cmd_destroy_lag(struct crete_lag *ldev, struct crete_core_dev *spec_dev)
|
||||
{
|
||||
int in_len = CRETE_ST_SZ_BYTES(destroy_lag_in);
|
||||
int out_len = CRETE_ST_SZ_BYTES(destroy_lag_out);
|
||||
void *in, *out, *lagc;
|
||||
int lagc_size = CRETE_ST_SZ_BYTES(lag_context);
|
||||
struct crete_core_dev *dev =
|
||||
spec_dev == NULL ? ldev->pf[CRETE_LAG_P1].dev : spec_dev;
|
||||
int status;
|
||||
int ret = 0;
|
||||
|
||||
in_len += lagc_size;
|
||||
|
||||
in = kvzalloc(in_len, GFP_KERNEL);
|
||||
if (!in) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
out = kvzalloc(out_len, GFP_KERNEL);
|
||||
if (!out) {
|
||||
ret = -ENOMEM;
|
||||
kvfree(in);
|
||||
goto done;
|
||||
}
|
||||
|
||||
CRETE_SET(destroy_lag_in, in, cmd_id, CRETE_CMD_LAG_CONFIG);
|
||||
CRETE_SET(destroy_lag_in, in, opcode, CRETE_DESTROY_LAG);
|
||||
lagc = CRETE_ADDR_OF(destroy_lag_in, in, lag_context);
|
||||
|
||||
CRETE_SET(lag_context, lagc, lag_id, dev->lag_cap.lag_id);
|
||||
|
||||
ret = crete_cmd_exec_polling(dev, in, in_len, out, sizeof(out));
|
||||
if (ret) {
|
||||
crete_info(dev->device, "destroy lag cmd err[%d]", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
status = CRETE_GET(destroy_lag_out, out, status);
|
||||
crete_info(dev->device, "destroy lag status:%d", status);
|
||||
|
||||
out:
|
||||
kfree(in);
|
||||
kfree(out);
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int crete_cmd_lag_enable(struct crete_core_dev *dev, u16 lag_enable)
|
||||
{
|
||||
int in_len = CRETE_ST_SZ_BYTES(lag_enable_in);
|
||||
int out_len = CRETE_ST_SZ_BYTES(lag_enable_out);
|
||||
void *in, *out;
|
||||
int status;
|
||||
int ret = 0;
|
||||
|
||||
in = kvzalloc(in_len, GFP_KERNEL);
|
||||
if (!in) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
out = kvzalloc(out_len, GFP_KERNEL);
|
||||
if (!out) {
|
||||
ret = -ENOMEM;
|
||||
kvfree(in);
|
||||
goto done;
|
||||
}
|
||||
|
||||
CRETE_SET(lag_enable_in, in, cmd_id, CRETE_CMD_ENABLE_LAG);
|
||||
CRETE_SET(lag_enable_in, in, opcode, 0);
|
||||
CRETE_SET(lag_enable_in, in, vport_id, dev->sfi_id);
|
||||
CRETE_SET(lag_enable_in, in, lag_enable, lag_enable);
|
||||
|
||||
ret = crete_cmd_exec_polling(dev, in, in_len, out, sizeof(out));
|
||||
if (ret) {
|
||||
crete_info(dev->device, "enable lag cmd err[%d]", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
status = CRETE_GET(lag_enable_out, out, status);
|
||||
crete_info(dev->device, "enable lag status:%d", status);
|
||||
|
||||
out:
|
||||
kfree(in);
|
||||
kfree(out);
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void crete_disable_lag(struct crete_lag *ldev, struct crete_core_dev *dev)
|
||||
{
|
||||
crete_cmd_destroy_lag(ldev, dev);
|
||||
ldev->mode = CRETE_LAG_INACTIVE;
|
||||
}
|
||||
|
||||
static void crete_do_bond(struct crete_lag *ldev)
|
||||
{
|
||||
bool do_bond;
|
||||
struct crete_lag_info lag_info = {};
|
||||
|
||||
if (!crete_lag_is_ready(ldev)) {
|
||||
do_bond = false;
|
||||
} else {
|
||||
lag_info = ldev->info;
|
||||
do_bond = lag_info.is_bonded;
|
||||
}
|
||||
|
||||
if (do_bond && !__crete_lag_is_active(ldev)) {
|
||||
crete_activate_lag(ldev);
|
||||
crete_modify_lag(ldev);
|
||||
} else if (do_bond && __crete_lag_is_active(ldev))
|
||||
crete_modify_lag(ldev);
|
||||
else if (!do_bond && __crete_lag_is_active(ldev))
|
||||
crete_disable_lag(ldev, NULL);
|
||||
}
|
||||
|
||||
static void crete_do_bond_work(struct work_struct *work)
|
||||
{
|
||||
struct delayed_work *delayed_work = to_delayed_work(work);
|
||||
struct crete_lag *ldev = container_of(delayed_work, struct crete_lag,
|
||||
bond_work);
|
||||
int status;
|
||||
|
||||
status = crete_dev_list_trylock();
|
||||
if (!status) {
|
||||
crete_queue_bond_work(ldev, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&ldev->lock);
|
||||
|
||||
crete_do_bond(ldev);
|
||||
mutex_unlock(&ldev->lock);
|
||||
crete_dev_list_unlock();
|
||||
}
|
||||
|
||||
static int crete_lag_dev_get_netdev_idx(struct crete_lag *ldev,
|
||||
struct net_device *ndev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ldev->ports; i++) {
|
||||
/* add pointer protect*/
|
||||
if (ldev->pf[i].dev)
|
||||
if (ldev->pf[i].dev->netdev == ndev)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int crete_handle_changeupper_event(struct crete_lag *ldev,
|
||||
struct crete_lag_info *lag_info,
|
||||
struct netdev_notifier_changeupper_info *info)
|
||||
{
|
||||
struct net_device *upper = info->upper_dev, *ndev_tmp;
|
||||
struct netdev_lag_upper_info *lag_upper_info = NULL;
|
||||
struct bonding *bond = netdev_priv(upper);
|
||||
bool is_bonded, is_in_lag, mode_supported;
|
||||
bool has_inactive = 0;
|
||||
struct slave *slave;
|
||||
u8 bond_status = 0;
|
||||
int num_slaves = 0;
|
||||
int changed = 0;
|
||||
int idx;
|
||||
|
||||
if (!netif_is_lag_master(upper))
|
||||
return 0;
|
||||
|
||||
if (info->linking)
|
||||
lag_upper_info = info->upper_info;
|
||||
|
||||
rcu_read_lock();
|
||||
for_each_netdev_in_bond_rcu(upper, ndev_tmp) {
|
||||
idx = crete_lag_dev_get_netdev_idx(ldev, ndev_tmp);
|
||||
if (idx >= 0) {
|
||||
slave = bond_slave_get_rcu(ndev_tmp);
|
||||
if (slave)
|
||||
has_inactive |= bond_is_slave_inactive(slave);
|
||||
bond_status |= (1 << idx);
|
||||
}
|
||||
|
||||
num_slaves++;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
if (!(bond_status & GENMASK(ldev->ports - 1, 0)))
|
||||
return 0;
|
||||
|
||||
if (lag_upper_info) {
|
||||
lag_info->tx_type = lag_upper_info->tx_type;
|
||||
lag_info->hash_type = lag_upper_info->hash_type;
|
||||
}
|
||||
|
||||
if (bond)
|
||||
lag_info->upper_lag_mode = BOND_MODE(bond);
|
||||
|
||||
lag_info->has_inactive = has_inactive;
|
||||
is_in_lag = num_slaves == ldev->ports &&
|
||||
bond_status == GENMASK(ldev->ports - 1, 0);
|
||||
|
||||
/* Lag mode must be activebackup or hash. */
|
||||
mode_supported = ((1 << lag_info->upper_lag_mode) & ldev->mode_supported);
|
||||
|
||||
is_bonded = is_in_lag && mode_supported;
|
||||
if (lag_info->is_bonded != is_bonded) {
|
||||
lag_info->is_bonded = is_bonded;
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
if (!is_in_lag)
|
||||
return changed;
|
||||
|
||||
if (!crete_lag_is_ready(ldev))
|
||||
NL_SET_ERR_MSG_MOD(info->info.extack,
|
||||
"Can't activate LAG offload");
|
||||
else if (!mode_supported)
|
||||
NL_SET_ERR_MSG_MOD(info->info.extack,
|
||||
"Can't activate LAG offload, TX type isn't supported");
|
||||
|
||||
return changed;
|
||||
|
||||
}
|
||||
|
||||
static int crete_handle_changelowerstate_event(struct crete_lag *ldev,
|
||||
struct crete_lag_info *lag_info,
|
||||
struct net_device *ndev,
|
||||
struct netdev_notifier_changelowerstate_info *info)
|
||||
{
|
||||
struct netdev_lag_lower_state_info *lag_lower_info;
|
||||
int idx;
|
||||
|
||||
if (!netif_is_lag_port(ndev))
|
||||
return 0;
|
||||
|
||||
idx = crete_lag_dev_get_netdev_idx(ldev, ndev);
|
||||
if (idx < 0)
|
||||
return 0;
|
||||
|
||||
lag_lower_info = info->lower_state_info;
|
||||
if (!lag_lower_info)
|
||||
return 0;
|
||||
|
||||
lag_info->netdev_state[idx] = *lag_lower_info;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int crete_handle_changeinfodata_event(struct crete_lag *ldev,
|
||||
struct crete_lag_info *lag_info,
|
||||
struct net_device *ndev)
|
||||
{
|
||||
struct net_device *ndev_tmp;
|
||||
struct slave *slave;
|
||||
bool has_inactive = 0;
|
||||
int idx;
|
||||
|
||||
if (!netif_is_lag_master(ndev))
|
||||
return 0;
|
||||
|
||||
rcu_read_lock();
|
||||
for_each_netdev_in_bond_rcu(ndev, ndev_tmp) {
|
||||
idx = crete_lag_dev_get_netdev_idx(ldev, ndev_tmp);
|
||||
if (idx < 0)
|
||||
continue;
|
||||
|
||||
slave = bond_slave_get_rcu(ndev_tmp);
|
||||
if (slave)
|
||||
has_inactive |= bond_is_slave_inactive(slave);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
if (lag_info->has_inactive == has_inactive)
|
||||
return 0;
|
||||
|
||||
lag_info->has_inactive = has_inactive;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int crete_lag_netdev_event(struct notifier_block *this,
|
||||
unsigned long event, void *ptr)
|
||||
{
|
||||
struct net_device *ndev = netdev_notifier_info_to_dev(ptr);
|
||||
struct crete_lag_info info;
|
||||
struct crete_lag *ldev;
|
||||
int changed = 0, change_lower = 0;
|
||||
|
||||
if (event != NETDEV_CHANGEUPPER &&
|
||||
event != NETDEV_CHANGELOWERSTATE &&
|
||||
event != NETDEV_CHANGEINFODATA)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
ldev = container_of(this, struct crete_lag, nb);
|
||||
|
||||
info = ldev->info;
|
||||
|
||||
switch (event) {
|
||||
case NETDEV_CHANGEUPPER:
|
||||
changed = crete_handle_changeupper_event(ldev, &info, ptr);
|
||||
break;
|
||||
case NETDEV_CHANGELOWERSTATE:
|
||||
change_lower = crete_handle_changelowerstate_event(ldev, &info,
|
||||
ndev, ptr);
|
||||
break;
|
||||
case NETDEV_CHANGEINFODATA:
|
||||
changed = crete_handle_changeinfodata_event(ldev, &info, ndev);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ldev->info = info;
|
||||
|
||||
if (changed || change_lower) {
|
||||
pr_debug("func:%s--line:%d, changed:%d change_lower:%d\n",
|
||||
__func__, __LINE__, changed, change_lower);
|
||||
if (change_lower) {
|
||||
crete_queue_bond_work(ldev, 100);
|
||||
}
|
||||
else
|
||||
crete_queue_bond_work(ldev, 0);
|
||||
}
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct crete_lag *crete_lag_dev_alloc(struct crete_core_dev *dev)
|
||||
{
|
||||
struct crete_lag *ldev;
|
||||
|
||||
ldev = kzalloc(sizeof(*ldev), GFP_KERNEL);
|
||||
if (!ldev)
|
||||
return NULL;
|
||||
|
||||
ldev->wq = create_singlethread_workqueue("crete_lag");
|
||||
if (!ldev->wq) {
|
||||
kfree(ldev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
kref_init(&ldev->ref);
|
||||
mutex_init(&ldev->lock);
|
||||
INIT_DELAYED_WORK(&ldev->bond_work, crete_do_bond_work);
|
||||
|
||||
ldev->nb.notifier_call = crete_lag_netdev_event;
|
||||
if (register_netdevice_notifier_net(&init_net, &ldev->nb)) {
|
||||
ldev->nb.notifier_call = NULL;
|
||||
dev_err(dev->device, "failed to register LAG dev notifier\n");
|
||||
}
|
||||
|
||||
ldev->mode = CRETE_LAG_INACTIVE;
|
||||
ldev->ports = dev->lag_cap.num_ports;
|
||||
ldev->mode_supported = dev->lag_cap.mode_support;
|
||||
ldev->hash_supported = dev->lag_cap.hash_type;
|
||||
ldev->lag_id = dev->lag_cap.lag_id;
|
||||
|
||||
return ldev;
|
||||
}
|
||||
|
||||
static inline int crete_get_dev_index(struct crete_core_dev *dev)
|
||||
{
|
||||
int idx = dev->lag_cap.pf_id;;
|
||||
|
||||
if (idx >= 0 && idx < CRETE_MAX_LAG_PORTS)
|
||||
return idx;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void crete_ldev_add(struct crete_lag *ldev, struct crete_core_dev *dev)
|
||||
{
|
||||
int fn = crete_get_dev_index(dev);
|
||||
|
||||
if (fn >= ldev->ports || fn < 0) {
|
||||
dev_dbg(dev->device, "can't support lag, port id:%d\n", fn);
|
||||
return;
|
||||
}
|
||||
|
||||
ldev->pf[fn].dev = dev;
|
||||
dev->lag_dev = ldev;
|
||||
|
||||
ldev->port_flags |= 1 << fn;
|
||||
|
||||
if (ldev->port_flags == GENMASK(ldev->ports - 1, 0)) {
|
||||
crete_disable_lag(ldev, NULL);
|
||||
|
||||
set_bit(CRETE_LAG_READY, &ldev->state_flags);
|
||||
}
|
||||
}
|
||||
|
||||
static int __crete_lag_dev_add(struct crete_core_dev *dev)
|
||||
{
|
||||
struct crete_lag *ldev = NULL;
|
||||
struct crete_core_dev *tmp_dev;
|
||||
|
||||
tmp_dev = crete_get_next_phy_dev_lag(dev);
|
||||
if (tmp_dev) {
|
||||
dev_info(dev->device, "found peer core dev:%s\n", dev_name(tmp_dev->device));
|
||||
ldev = tmp_dev->lag_dev;
|
||||
}
|
||||
|
||||
if (!ldev) {
|
||||
ldev = crete_lag_dev_alloc(dev);
|
||||
if (!ldev) {
|
||||
dev_err(dev->device, "failed to alloc lag dev\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
crete_ldev_add(ldev, dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mutex_lock(&ldev->lock);
|
||||
crete_ldev_get(ldev);
|
||||
crete_ldev_add(ldev, dev);
|
||||
mutex_unlock(&ldev->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int crete_get_lag_cap(struct crete_core_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
int in_len = CRETE_ST_SZ_BYTES(get_lag_cap_in);
|
||||
int out_len = CRETE_ST_SZ_BYTES(get_lag_cap_out);
|
||||
void *in, *out;
|
||||
u8 status;
|
||||
|
||||
in = kvzalloc(in_len, GFP_KERNEL);
|
||||
if (!in) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
out = kvzalloc(out_len, GFP_KERNEL);
|
||||
if (!out) {
|
||||
ret = -ENOMEM;
|
||||
kvfree(in);
|
||||
goto done;
|
||||
}
|
||||
|
||||
CRETE_SET(get_lag_cap_in, in, cmd_id, CRETE_CMD_GET_LAG_CAP);
|
||||
CRETE_SET(get_lag_cap_in, in, opcode, 0);
|
||||
CRETE_SET(get_lag_cap_in, in, vport_id, dev->sfi_id);
|
||||
|
||||
ret = crete_cmd_exec_polling(dev, in, in_len, out, out_len);
|
||||
if (ret < 0)
|
||||
goto err_out;
|
||||
|
||||
status = CRETE_GET(get_lag_cap_out, out, status);
|
||||
if (status != SUCCESS) {
|
||||
u32 err_type = CRETE_GET(get_lag_cap_out, out, err_type);
|
||||
|
||||
crete_err(dev->device,
|
||||
"crete get lag cap failed, status:0x%x err type:0x%x\n",
|
||||
status, err_type);
|
||||
ret = -EINVAL;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
dev->lag_cap.lag_master = CRETE_GET(get_lag_cap_out, out, lag_master);
|
||||
dev->lag_cap.lag_id = CRETE_GET(get_lag_cap_out, out, lag_id);
|
||||
dev->lag_cap.mode_support = CRETE_GET(get_lag_cap_out, out, mode_support);
|
||||
dev->lag_cap.hash_type = CRETE_GET(get_lag_cap_out, out, hash_type);
|
||||
dev->lag_cap.num_ports = CRETE_GET(get_lag_cap_out, out, num_ports);
|
||||
dev->lag_cap.pf_id = CRETE_GET(get_lag_cap_out, out, pf_id);
|
||||
|
||||
err_out:
|
||||
kvfree(in);
|
||||
kvfree(out);
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int crete_lag_add(struct crete_core_dev *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
dev->lag_enable = CRETE_LAG_UNSUPPORT;
|
||||
ret = crete_get_lag_cap(dev);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
|
||||
crete_add_lag_enable_debugfs(dev);
|
||||
|
||||
if (!crete_lag_is_supported(dev))
|
||||
goto done;
|
||||
|
||||
dev->lag_enable = CRETE_LAG_ENABLE;
|
||||
recheck:
|
||||
crete_dev_list_lock();
|
||||
ret = __crete_lag_dev_add(dev);
|
||||
crete_dev_list_unlock();
|
||||
|
||||
if (ret) {
|
||||
msleep(50);
|
||||
goto recheck;
|
||||
}
|
||||
|
||||
if (dev->lag_dev)
|
||||
crete_ldev_add_debugfs(dev);
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void crete_ldev_remove(struct crete_lag *ldev, struct crete_core_dev *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ldev->ports; i++)
|
||||
if (ldev->pf[i].dev == dev)
|
||||
break;
|
||||
|
||||
if (i == ldev->ports) {
|
||||
if (__crete_lag_is_active(ldev))
|
||||
crete_disable_lag(ldev, dev);
|
||||
return;
|
||||
}
|
||||
|
||||
ldev->pf[i].dev = NULL;
|
||||
dev->lag_dev = NULL;
|
||||
}
|
||||
|
||||
void crete_lag_remove(struct crete_core_dev *dev)
|
||||
{
|
||||
struct crete_lag *ldev;
|
||||
|
||||
ldev = dev->lag_dev;
|
||||
if (!ldev)
|
||||
return;
|
||||
|
||||
crete_ldev_remove_debugfs(dev->dbg.lag_debugfs);
|
||||
mutex_lock(&ldev->lock);
|
||||
crete_ldev_remove(ldev, dev);
|
||||
mutex_unlock(&ldev->lock);
|
||||
crete_ldev_put(ldev);
|
||||
}
|
@ -0,0 +1,126 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __CRETE_LAG_H__
|
||||
#define __CRETE_LAG_H__
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include "crete.h"
|
||||
|
||||
|
||||
#define CRETE_MAX_LAG_PORTS 4
|
||||
#define CRETE_MIN_LAG_PORTS 2
|
||||
|
||||
#ifndef DEFINE_SHOW_STORE_ATTRIBUTE
|
||||
#define DEFINE_SHOW_STORE_ATTRIBUTE(__name) \
|
||||
static int __name ## _open(struct inode *inode, struct file *file) \
|
||||
{ \
|
||||
return single_open(file, __name ## _show, inode->i_private); \
|
||||
} \
|
||||
\
|
||||
static const struct file_operations __name ## _fops = { \
|
||||
.owner = THIS_MODULE, \
|
||||
.open = __name ## _open, \
|
||||
.read = seq_read, \
|
||||
.write = __name ## _write, \
|
||||
.llseek = seq_lseek, \
|
||||
.release = single_release, \
|
||||
}
|
||||
#endif
|
||||
|
||||
struct crete_lag_cap {
|
||||
u8 lag_master;
|
||||
u8 lag_id;
|
||||
u8 mode_support;
|
||||
u8 hash_type;
|
||||
u8 num_ports;
|
||||
u8 pf_id;
|
||||
u8 resv[2];
|
||||
};
|
||||
|
||||
enum {
|
||||
CRETE_LAG_P1,
|
||||
CRETE_LAG_P2,
|
||||
CRETE_LAG_P3,
|
||||
CRETE_LAG_P4,
|
||||
};
|
||||
|
||||
enum crete_lag_mode {
|
||||
CRETE_LAG_INACTIVE,
|
||||
CRETE_LAG_ACTIVE,
|
||||
};
|
||||
|
||||
enum crete_lag_state {
|
||||
CRETE_LAG_READY,
|
||||
};
|
||||
|
||||
enum crete_lag_pri {
|
||||
CRETE_LAG_DISABLE,
|
||||
CRETE_LAG_ENABLE,
|
||||
CRETE_LAG_UNSUPPORT,
|
||||
CRETE_LAG_PRI_MAX,
|
||||
};
|
||||
|
||||
/* Used for collection of netdev event info. */
|
||||
struct crete_lag_info {
|
||||
enum netdev_lag_tx_type tx_type;
|
||||
struct netdev_lag_lower_state_info netdev_state[CRETE_MAX_LAG_PORTS];
|
||||
unsigned int is_bonded:1;
|
||||
unsigned int has_inactive:1;
|
||||
enum netdev_lag_hash hash_type;
|
||||
u8 upper_lag_mode;
|
||||
u8 active_port;
|
||||
u8 netdev_idx;
|
||||
};
|
||||
|
||||
struct crete_lag_func {
|
||||
struct crete_core_dev *dev;
|
||||
//struct net_device *netdev;
|
||||
bool has_drop;
|
||||
};
|
||||
|
||||
struct crete_lag {
|
||||
enum crete_lag_mode mode;
|
||||
unsigned long state_flags;
|
||||
u8 port_flags;
|
||||
u8 ports;
|
||||
u8 mode_supported;
|
||||
u8 hash_supported;
|
||||
u8 lag_id;
|
||||
struct kref ref;
|
||||
struct crete_lag_func pf[CRETE_MAX_LAG_PORTS];
|
||||
struct crete_lag_info info;
|
||||
struct workqueue_struct *wq;
|
||||
struct delayed_work bond_work;
|
||||
struct notifier_block nb;
|
||||
|
||||
struct mutex lock;
|
||||
};
|
||||
|
||||
static inline bool crete_is_supported_lag(struct crete_core_dev *dev)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool crete_lag_is_ready(struct crete_lag *ldev)
|
||||
{
|
||||
return test_bit(CRETE_LAG_READY, &ldev->state_flags);
|
||||
}
|
||||
|
||||
static inline bool __crete_lag_is_active(struct crete_lag *ldev)
|
||||
{
|
||||
return (ldev->mode == CRETE_LAG_ACTIVE);
|
||||
}
|
||||
|
||||
void crete_ldev_add_debugfs(struct crete_core_dev *dev);
|
||||
void crete_add_lag_enable_debugfs(struct crete_core_dev *dev);
|
||||
void crete_ldev_remove_debugfs(struct dentry *dbg);
|
||||
int crete_lag_add(struct crete_core_dev *dev);
|
||||
void crete_lag_remove(struct crete_core_dev *dev);
|
||||
int crete_cmd_lag_enable(struct crete_core_dev *dev, u16 lag_enable);
|
||||
|
||||
#if 0
|
||||
void crete_lag_add_netdev(struct crete_core_dev *dev,
|
||||
struct net_device *netdev);
|
||||
void crete_lag_remove_netdev(struct crete_core_dev *dev,
|
||||
struct net_device *netdev);
|
||||
#endif
|
||||
#endif
|
@ -0,0 +1,196 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#include "crete.h"
|
||||
|
||||
static int state_show(struct seq_file *file, void *priv)
|
||||
{
|
||||
struct crete_core_dev *dev = file->private;
|
||||
struct crete_lag *ldev;
|
||||
bool active;
|
||||
|
||||
ldev = dev->lag_dev;
|
||||
mutex_lock(&ldev->lock);
|
||||
active = __crete_lag_is_active(ldev);
|
||||
mutex_unlock(&ldev->lock);
|
||||
seq_printf(file, "%s\n", active ? "active" : "disabled");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int members_show(struct seq_file *file, void *priv)
|
||||
{
|
||||
struct crete_core_dev *dev = file->private;
|
||||
struct crete_lag *ldev;
|
||||
int i;
|
||||
|
||||
ldev = dev->lag_dev;
|
||||
mutex_lock(&ldev->lock);
|
||||
for (i = 0; i < ldev->ports; i++) {
|
||||
if (!ldev->pf[i].dev)
|
||||
continue;
|
||||
seq_printf(file, "%s\n", dev_name(ldev->pf[i].dev->device));
|
||||
}
|
||||
mutex_unlock(&ldev->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mode_show(struct seq_file *file, void *priv)
|
||||
{
|
||||
struct crete_core_dev *dev = file->private;
|
||||
struct crete_lag *ldev = dev->lag_dev;
|
||||
|
||||
mutex_lock(&ldev->lock);
|
||||
seq_printf(file, "0x%x\n", ldev->mode_supported);
|
||||
mutex_unlock(&ldev->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hash_show(struct seq_file *file, void *priv)
|
||||
{
|
||||
struct crete_core_dev *dev = file->private;
|
||||
struct crete_lag *ldev = dev->lag_dev;
|
||||
|
||||
mutex_lock(&ldev->lock);
|
||||
seq_printf(file, "0x%x\n", ldev->hash_supported);
|
||||
mutex_unlock(&ldev->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int lag_id_show(struct seq_file *file, void *priv)
|
||||
{
|
||||
struct crete_core_dev *dev = file->private;
|
||||
struct crete_lag *ldev = dev->lag_dev;
|
||||
|
||||
mutex_lock(&ldev->lock);
|
||||
seq_printf(file, "0x%x\n", ldev->lag_id);
|
||||
mutex_unlock(&ldev->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max_port_show(struct seq_file *file, void *priv)
|
||||
{
|
||||
struct crete_core_dev *dev = file->private;
|
||||
struct crete_lag *ldev = dev->lag_dev;
|
||||
|
||||
mutex_lock(&ldev->lock);
|
||||
seq_printf(file, "0x%x\n", ldev->ports);
|
||||
mutex_unlock(&ldev->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t lag_enable_write(struct file *file,
|
||||
const char __user *ubuf,
|
||||
size_t len, loff_t *offp)
|
||||
{
|
||||
struct seq_file *m = file->private_data;
|
||||
struct crete_core_dev *dev = m->private;
|
||||
u16 lag_enable;
|
||||
int ret;
|
||||
|
||||
if (dev->lag_enable == CRETE_LAG_UNSUPPORT)
|
||||
return -EINVAL;
|
||||
|
||||
ret = kstrtou16_from_user(ubuf, len, 10, &lag_enable);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (lag_enable != CRETE_LAG_DISABLE &&
|
||||
lag_enable != CRETE_LAG_ENABLE)
|
||||
return -EINVAL;
|
||||
|
||||
if (lag_enable == dev->lag_enable)
|
||||
return len;
|
||||
|
||||
ret = crete_cmd_lag_enable(dev, lag_enable);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev->lag_enable = lag_enable;
|
||||
*offp += len;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int lag_enable_show(struct seq_file *m, void *data)
|
||||
{
|
||||
struct crete_core_dev *dev = m->private;
|
||||
|
||||
if (dev->lag_enable == CRETE_LAG_ENABLE)
|
||||
seq_puts(m, "lag is enabled\n");
|
||||
else if (dev->lag_enable == CRETE_LAG_DISABLE)
|
||||
seq_puts(m, "lag is disabled\n");
|
||||
else
|
||||
seq_puts(m, "lag is unsupported\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_SHOW_ATTRIBUTE(state);
|
||||
DEFINE_SHOW_ATTRIBUTE(members);
|
||||
DEFINE_SHOW_ATTRIBUTE(mode);
|
||||
DEFINE_SHOW_ATTRIBUTE(hash);
|
||||
DEFINE_SHOW_ATTRIBUTE(lag_id);
|
||||
DEFINE_SHOW_ATTRIBUTE(max_port);
|
||||
DEFINE_SHOW_STORE_ATTRIBUTE(lag_enable);
|
||||
|
||||
void crete_add_lag_enable_debugfs(struct crete_core_dev *dev)
|
||||
{
|
||||
debugfs_create_file("lag_enable", 0644, crete_debugfs_get_dev_root(dev),
|
||||
dev, &lag_enable_fops);
|
||||
}
|
||||
|
||||
void crete_ldev_add_debugfs(struct crete_core_dev *dev)
|
||||
{
|
||||
struct dentry *dbg;
|
||||
|
||||
dbg = debugfs_create_dir("lag", crete_debugfs_get_dev_root(dev));
|
||||
dev->dbg.lag_debugfs = dbg;
|
||||
|
||||
debugfs_create_file("state", 0444, dbg, dev, &state_fops);
|
||||
debugfs_create_file("members", 0444, dbg, dev, &members_fops);
|
||||
debugfs_create_file("mode_supported", 0444, dbg, dev, &mode_fops);
|
||||
debugfs_create_file("hash_supported", 0444, dbg, dev, &hash_fops);
|
||||
debugfs_create_file("lag_id", 0444, dbg, dev, &lag_id_fops);
|
||||
debugfs_create_file("max_port", 0444, dbg, dev, &max_port_fops);
|
||||
}
|
||||
|
||||
void crete_ldev_remove_debugfs(struct dentry *dbg)
|
||||
{
|
||||
debugfs_remove_recursive(dbg);
|
||||
}
|
||||
|
@ -0,0 +1,589 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (C) 2018-2019, Intel Corporation. */
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pldmfw.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uuid.h>
|
||||
#include "crete_pldmfw_lib.h"
|
||||
#include "crete_regs.h"
|
||||
|
||||
/**
|
||||
* crete_pldm_check_fw_space - Verify that the firmware image has space left
|
||||
* @data: pointer to private data
|
||||
* @offset: offset to start from
|
||||
* @length: length to check for
|
||||
*
|
||||
* Verify that the firmware data can hold a chunk of bytes with the specified
|
||||
* offset and length.
|
||||
*
|
||||
* Returns: zero on success, or -EFAULT if the image does not have enough
|
||||
* space left to fit the expected length.
|
||||
*/
|
||||
static int
|
||||
crete_pldm_check_fw_space(struct crete_pldmfw_priv *data, size_t offset, size_t length)
|
||||
{
|
||||
size_t expected_size = offset + length;
|
||||
struct device *dev = data->context->dev;
|
||||
|
||||
if (data->fw->size < expected_size) {
|
||||
dev_err(dev, "Firmware file size smaller than expected. Got %zu bytes, needed %zu bytes\n",
|
||||
data->fw->size, expected_size);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* crete_pldm_move_fw_offset - Move the current firmware offset forward
|
||||
* @data: pointer to private data
|
||||
* @bytes_to_move: number of bytes to move the offset forward by
|
||||
*
|
||||
* Check that there is enough space past the current offset, and then move the
|
||||
* offset forward by this amount.
|
||||
*
|
||||
* Returns: zero on success, or -EFAULT if the image is too small to fit the
|
||||
* expected length.
|
||||
*/
|
||||
static int
|
||||
crete_pldm_move_fw_offset(struct crete_pldmfw_priv *data, size_t bytes_to_move)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = crete_pldm_check_fw_space(data, data->offset, bytes_to_move);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
data->offset += bytes_to_move;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* crete_pldm_parse_header - Validate and extract details about the PLDM header
|
||||
* @data: pointer to private data
|
||||
*
|
||||
* Performs initial basic verification of the PLDM image, up to the first
|
||||
* firmware record.
|
||||
*
|
||||
* This includes the following checks and extractions
|
||||
*
|
||||
* * Verify that the UUID at the start of the header matches the expected
|
||||
* value as defined in the DSP0267 PLDM specification
|
||||
* * Check that the revision is 0x01
|
||||
* * Extract the total header_size and verify that the image is large enough
|
||||
* to contain at least the length of this header
|
||||
* * Extract the size of the component bitmap length
|
||||
* * Extract a pointer to the start of the record area
|
||||
*
|
||||
* Returns: zero on success, or a negative error code on failure.
|
||||
*/
|
||||
static int crete_pldm_parse_header(struct crete_pldmfw_priv *data)
|
||||
{
|
||||
const struct __pldmfw_record_area *record_area;
|
||||
struct device *dev = data->context->dev;
|
||||
const struct __pldm_header *header;
|
||||
size_t header_size;
|
||||
int err;
|
||||
|
||||
err = crete_pldm_move_fw_offset(data, sizeof(*header));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
header = (const struct __pldm_header *)data->fw->data;
|
||||
data->header = header;
|
||||
|
||||
if (!uuid_equal(&header->id, &pldm_firmware_header_id)) {
|
||||
dev_err(dev, "Invalid package header identifier. Expected UUID %pUB, but got %pUB\n",
|
||||
&pldm_firmware_header_id, &header->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (header->revision != PACKAGE_HEADER_FORMAT_REVISION) {
|
||||
dev_err(dev, "Invalid package header revision. Expected revision %u but got %u\n",
|
||||
PACKAGE_HEADER_FORMAT_REVISION, header->revision);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
data->total_header_size = get_unaligned_le16(&header->size);
|
||||
header_size = data->total_header_size - sizeof(*header);
|
||||
|
||||
err = crete_pldm_check_fw_space(data, data->offset, header_size);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
data->component_bitmap_len =
|
||||
get_unaligned_le16(&header->component_bitmap_len);
|
||||
|
||||
if (data->component_bitmap_len % 8 != 0) {
|
||||
dev_err(dev, "Invalid component bitmap length. The length is %u, which is not a multiple of 8\n",
|
||||
data->component_bitmap_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
data->bitmap_size = data->component_bitmap_len / 8;
|
||||
|
||||
err = crete_pldm_move_fw_offset(data, header->version_len);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* extract a pointer to the record area, which just follows the main
|
||||
* PLDM header data.
|
||||
*/
|
||||
record_area = (const struct __pldmfw_record_area *)(data->fw->data +
|
||||
data->offset);
|
||||
|
||||
err = crete_pldm_move_fw_offset(data, sizeof(*record_area));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
data->record_count = record_area->record_count;
|
||||
data->record_start = record_area->records;
|
||||
dev_info(dev, "data->offset [0x%lx] record_count [%d] record_start [%p]\n", data->offset,
|
||||
record_area->record_count, record_area->records);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* crete_pldm_check_desc_tlv_len - Check that the length matches expectation
|
||||
* @data: pointer to image details
|
||||
* @type: the descriptor type
|
||||
* @size: the length from the descriptor header
|
||||
*
|
||||
* If the descriptor type is one of the documented descriptor types according
|
||||
* to the standard, verify that the provided length matches.
|
||||
*
|
||||
* If the type is not recognized or is VENDOR_DEFINED, return zero.
|
||||
*
|
||||
* Returns: zero on success, or -EINVAL if the specified size of a standard
|
||||
* TLV does not match the expected value defined for that TLV.
|
||||
*/
|
||||
static int
|
||||
crete_pldm_check_desc_tlv_len(struct crete_pldmfw_priv *data, u16 type, u16 size)
|
||||
{
|
||||
struct device *dev = data->context->dev;
|
||||
u16 expected_size;
|
||||
|
||||
switch (type) {
|
||||
case PLDM_DESC_ID_PCI_VENDOR_ID:
|
||||
case PLDM_DESC_ID_PCI_DEVICE_ID:
|
||||
case PLDM_DESC_ID_PCI_SUBVENDOR_ID:
|
||||
case PLDM_DESC_ID_PCI_SUBDEV_ID:
|
||||
expected_size = 2;
|
||||
break;
|
||||
case PLDM_DESC_ID_PCI_REVISION_ID:
|
||||
expected_size = 1;
|
||||
break;
|
||||
case PLDM_DESC_ID_PNP_VENDOR_ID:
|
||||
expected_size = 3;
|
||||
break;
|
||||
case PLDM_DESC_ID_IANA_ENTERPRISE_ID:
|
||||
case PLDM_DESC_ID_ACPI_VENDOR_ID:
|
||||
case PLDM_DESC_ID_PNP_PRODUCT_ID:
|
||||
case PLDM_DESC_ID_ACPI_PRODUCT_ID:
|
||||
expected_size = 4;
|
||||
break;
|
||||
case PLDM_DESC_ID_UUID:
|
||||
expected_size = 16;
|
||||
break;
|
||||
case PLDM_DESC_ID_VENDOR_DEFINED:
|
||||
return 0;
|
||||
default:
|
||||
/* Do not report an error on an unexpected TLV */
|
||||
dev_err(dev, "Found unrecognized TLV type 0x%04x\n", type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (size != expected_size) {
|
||||
dev_err(dev, "Found TLV type 0x%04x with unexpected length. Got %u bytes, but expected %u bytes\n",
|
||||
type, size, expected_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pldm_parse_desc_tlvs - Check and skip past a number of TLVs
|
||||
* @data: pointer to private data
|
||||
* @record: pointer to the record this TLV belongs too
|
||||
* @desc_count: descriptor count
|
||||
*
|
||||
* From the current offset, read and extract the descriptor TLVs, updating the
|
||||
* current offset each time.
|
||||
*
|
||||
* Returns: zero on success, or a negative error code on failure.
|
||||
*/
|
||||
static int
|
||||
crete_pldm_parse_desc_tlvs(struct crete_pldmfw_priv *data,
|
||||
struct pldmfw_record *record, u8 desc_count)
|
||||
{
|
||||
const struct __pldmfw_desc_tlv *__desc;
|
||||
const u8 *desc_start;
|
||||
u8 i;
|
||||
|
||||
desc_start = data->fw->data + data->offset;
|
||||
|
||||
pldm_for_each_desc_tlv(i, __desc, desc_start, desc_count) {
|
||||
struct pldmfw_desc_tlv *desc;
|
||||
int err;
|
||||
u16 type, size;
|
||||
|
||||
err = crete_pldm_move_fw_offset(data, sizeof(*__desc));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
type = get_unaligned_le16(&__desc->type);
|
||||
|
||||
/* According to DSP0267, this only includes the data field */
|
||||
size = get_unaligned_le16(&__desc->size);
|
||||
|
||||
err = crete_pldm_check_desc_tlv_len(data, type, size);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* check that we have space and move the offset forward */
|
||||
err = crete_pldm_move_fw_offset(data, size);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
desc = kzalloc(sizeof(*desc), GFP_KERNEL);
|
||||
if (!desc)
|
||||
return -ENOMEM;
|
||||
|
||||
desc->type = type;
|
||||
desc->size = size;
|
||||
desc->data = __desc->data;
|
||||
|
||||
list_add_tail(&desc->entry, &record->descs);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* crete_pldm_parse_one_record - Verify size of one PLDM record
|
||||
* @data: pointer to image details
|
||||
* @__record: pointer to the record to check
|
||||
*
|
||||
* This function checks that the record size does not exceed either the size
|
||||
* of the firmware file or the total length specified in the header section.
|
||||
*
|
||||
* It also verifies that the recorded length of the start of the record
|
||||
* matches the size calculated by adding the static structure length, the
|
||||
* component bitmap length, the version string length, the length of all
|
||||
* descriptor TLVs, and the length of the package data.
|
||||
*
|
||||
* Returns: zero on success, or a negative error code on failure.
|
||||
*/
|
||||
static int
|
||||
crete_pldm_parse_one_record(struct crete_pldmfw_priv *data,
|
||||
const struct __pldmfw_record_info *__record)
|
||||
{
|
||||
struct pldmfw_record *record;
|
||||
size_t measured_length;
|
||||
int err;
|
||||
const u8 *bitmap_ptr;
|
||||
u16 record_len;
|
||||
int i;
|
||||
|
||||
/* Make a copy and insert it into the record list */
|
||||
record = kzalloc(sizeof(*record), GFP_KERNEL);
|
||||
if (!record)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_LIST_HEAD(&record->descs);
|
||||
list_add_tail(&record->entry, &data->records);
|
||||
|
||||
/* Then check that we have space and move the offset */
|
||||
err = crete_pldm_move_fw_offset(data, sizeof(*__record));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
record_len = get_unaligned_le16(&__record->record_len);
|
||||
record->package_data_len = get_unaligned_le16(&__record->package_data_len);
|
||||
record->device_update_flags = get_unaligned_le32(&__record->device_update_flags);
|
||||
record->version_len = __record->version_len;
|
||||
record->version_type = __record->version_type;
|
||||
|
||||
bitmap_ptr = data->fw->data + data->offset;
|
||||
|
||||
/* check that we have space for the component bitmap length */
|
||||
err = crete_pldm_move_fw_offset(data, data->bitmap_size);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
record->component_bitmap_len = data->component_bitmap_len;
|
||||
record->component_bitmap = bitmap_zalloc(record->component_bitmap_len,
|
||||
GFP_KERNEL);
|
||||
if (!record->component_bitmap)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < data->bitmap_size; i++)
|
||||
bitmap_set_value8(record->component_bitmap, bitmap_ptr[i], i * 8);
|
||||
|
||||
record->version_string = data->fw->data + data->offset;
|
||||
|
||||
err = crete_pldm_move_fw_offset(data, record->version_len);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Scan through the descriptor TLVs and find the end */
|
||||
err = crete_pldm_parse_desc_tlvs(data, record, __record->descriptor_count);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
record->package_data = data->fw->data + data->offset;
|
||||
|
||||
err = crete_pldm_move_fw_offset(data, record->package_data_len);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
measured_length = data->offset - ((const u8 *)__record - data->fw->data);
|
||||
if (measured_length != record_len) {
|
||||
dev_err(data->context->dev, "Unexpected record length. Measured record length is %zu bytes, expected length is %u bytes\n",
|
||||
measured_length, record_len);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* crete_pldm_parse_records - Locate the start of the component area
|
||||
* @data: pointer to private data
|
||||
*
|
||||
* Extract the record count, and loop through each record, searching for the
|
||||
* component area.
|
||||
*
|
||||
* Returns: zero on success, or a negative error code on failure.
|
||||
*/
|
||||
static int crete_pldm_parse_records(struct crete_pldmfw_priv *data)
|
||||
{
|
||||
const struct __pldmfw_component_area *component_area;
|
||||
const struct __pldmfw_record_info *record;
|
||||
int err;
|
||||
u8 i;
|
||||
|
||||
pldm_for_each_record(i, record, data->record_start, data->record_count) {
|
||||
err = crete_pldm_parse_one_record(data, record);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Extract a pointer to the component area, which just follows the
|
||||
* PLDM device record data.
|
||||
*/
|
||||
component_area = (const struct __pldmfw_component_area *)(data->fw->data + data->offset);
|
||||
|
||||
err = crete_pldm_move_fw_offset(data, sizeof(*component_area));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
data->component_count =
|
||||
get_unaligned_le16(&component_area->component_image_count);
|
||||
data->component_start = component_area->components;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* crete_pldm_parse_components - Locate the CRC header checksum
|
||||
* @data: pointer to private data
|
||||
*
|
||||
* Extract the component count, and find the pointer to the component area.
|
||||
* Scan through each component searching for the end, which should point to
|
||||
* the package header checksum.
|
||||
*
|
||||
* Extract the package header CRC and save it for verification.
|
||||
*
|
||||
* Returns: zero on success, or a negative error code on failure.
|
||||
*/
|
||||
static int crete_pldm_parse_components(struct crete_pldmfw_priv *data)
|
||||
{
|
||||
const struct __pldmfw_component_info *__component;
|
||||
struct device *dev = data->context->dev;
|
||||
const u8 *header_crc_ptr;
|
||||
int err;
|
||||
u8 i;
|
||||
|
||||
pldm_for_each_component(i, __component, data->component_start, data->component_count) {
|
||||
struct pldmfw_component *component;
|
||||
u32 offset, size;
|
||||
|
||||
err = crete_pldm_move_fw_offset(data,
|
||||
sizeof(*__component) + COMPONENT_OPAQUE_DATA_LENGTH);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = crete_pldm_move_fw_offset(data, __component->version_len);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
offset = get_unaligned_le32(&__component->location_offset);
|
||||
size = get_unaligned_le32(&__component->size);
|
||||
|
||||
err = crete_pldm_check_fw_space(data, offset, size);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
component = kzalloc(sizeof(*component), GFP_KERNEL);
|
||||
if (!component)
|
||||
return -ENOMEM;
|
||||
|
||||
component->index = i;
|
||||
component->classification = get_unaligned_le16(&__component->classification);
|
||||
component->identifier = get_unaligned_le16(&__component->identifier);
|
||||
component->comparison_stamp = get_unaligned_le32(&__component->comparison_stamp);
|
||||
component->options = get_unaligned_le16(&__component->options);
|
||||
component->activation_method = get_unaligned_le16(&__component->activation_method);
|
||||
component->version_type = __component->version_type;
|
||||
component->version_len = __component->version_len;
|
||||
component->version_string = __component->version_string;
|
||||
component->component_data = data->fw->data + offset;
|
||||
component->component_size = size;
|
||||
|
||||
list_add_tail(&component->entry, &data->components);
|
||||
}
|
||||
|
||||
header_crc_ptr = data->fw->data + data->offset;
|
||||
// dev_err(dev, "printk CRC:\n");
|
||||
// hexdump((char *)header_crc_ptr, sizeof(data->header_crc));
|
||||
|
||||
err = crete_pldm_move_fw_offset(data, sizeof(data->header_crc));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Make sure that we reached the expected offset */
|
||||
if (data->offset != data->total_header_size) {
|
||||
dev_err(dev, "Invalid firmware header size. Expected %u but got %zu\n",
|
||||
data->total_header_size, data->offset);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
data->header_crc = get_unaligned_le32(header_crc_ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* crete_pldm_verify_header_crc - Verify that the CRC in the header matches
|
||||
* @data: pointer to private data
|
||||
*
|
||||
* Calculates the 32-bit CRC using the standard IEEE 802.3 CRC polynomial and
|
||||
* compares it to the value stored in the header.
|
||||
*
|
||||
* Returns: zero on success if the CRC matches, or -EBADMSG on an invalid CRC.
|
||||
*/
|
||||
static int crete_pldm_verify_header_crc(struct crete_pldmfw_priv *data)
|
||||
{
|
||||
struct device *dev = data->context->dev;
|
||||
u32 calculated_crc;
|
||||
size_t length;
|
||||
|
||||
/* Calculate the 32-bit CRC of the header contents up to but
|
||||
* not including the checksum. Note that the Linux crc32_le function
|
||||
* does not perform an expected final XOR.
|
||||
*/
|
||||
length = data->offset - sizeof(data->header_crc);
|
||||
calculated_crc = crc32_le(~0, data->fw->data, length) ^ ~0;
|
||||
|
||||
if (calculated_crc != data->header_crc) {
|
||||
dev_err(dev, "Invalid CRC in firmware header. Got 0x%08x but expected 0x%08x\n",
|
||||
calculated_crc, data->header_crc);
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* crete_pldmfw_free_priv - Free memory allocated while parsing the PLDM image
|
||||
* @data: pointer to the PLDM data structure
|
||||
*
|
||||
* Loops through and clears all allocated memory associated with each
|
||||
* allocated descriptor, record, and component.
|
||||
*/
|
||||
void crete_pldmfw_free_priv(struct crete_pldmfw_priv *data)
|
||||
{
|
||||
struct pldmfw_component *component, *c_safe;
|
||||
struct pldmfw_record *record, *r_safe;
|
||||
struct pldmfw_desc_tlv *desc, *d_safe;
|
||||
|
||||
list_for_each_entry_safe(component, c_safe, &data->components, entry) {
|
||||
list_del(&component->entry);
|
||||
kfree(component);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(record, r_safe, &data->records, entry) {
|
||||
list_for_each_entry_safe(desc, d_safe, &record->descs, entry) {
|
||||
list_del(&desc->entry);
|
||||
kfree(desc);
|
||||
}
|
||||
|
||||
if (record->component_bitmap) {
|
||||
bitmap_free(record->component_bitmap);
|
||||
record->component_bitmap = NULL;
|
||||
}
|
||||
|
||||
list_del(&record->entry);
|
||||
kfree(record);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(crete_pldmfw_free_priv);
|
||||
|
||||
/**
|
||||
* crete_pldm_parse_image - parse and extract details from PLDM image
|
||||
* @data: pointer to private data
|
||||
*
|
||||
* Verify that the firmware file contains valid data for a PLDM firmware
|
||||
* file. Extract useful pointers and data from the firmware file and store
|
||||
* them in the data structure.
|
||||
*
|
||||
* The PLDM firmware file format is defined in DMTF DSP0267 1.0.0. Care
|
||||
* should be taken to use get_unaligned_le* when accessing data from the
|
||||
* pointers in data.
|
||||
*
|
||||
* Returns: zero on success, or a negative error code on failure.
|
||||
*/
|
||||
int crete_pldm_parse_image(struct crete_pldmfw_priv *data)
|
||||
{
|
||||
int err;
|
||||
struct device *dev = data->context->dev;
|
||||
|
||||
if (WARN_ON(!(data->context->dev && data->fw->data && data->fw->size)))
|
||||
return -EINVAL;
|
||||
|
||||
err = crete_pldm_parse_header(data);
|
||||
if (err) {
|
||||
dev_err(dev, "crete_pldm parse_header failed err %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = crete_pldm_parse_records(data);
|
||||
if (err) {
|
||||
dev_err(dev, "crete_pldm parse_records failed err %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = crete_pldm_parse_components(data);
|
||||
if (err) {
|
||||
dev_err(dev, "crete_pldm parse_components failed err %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return crete_pldm_verify_header_crc(data);
|
||||
}
|
||||
EXPORT_SYMBOL(crete_pldm_parse_image);
|
||||
|
||||
|
||||
MODULE_AUTHOR("Jacob Keller <jacob.e.keller@intel.com>");
|
||||
MODULE_DESCRIPTION("PLDM firmware flash update library");
|
@ -0,0 +1,278 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (C) 2018-2019, Intel Corporation. */
|
||||
|
||||
#ifndef _CRETE_PLDMFW_LIB_H_
|
||||
#define _CRETE_PLDMFW_LIB_H_
|
||||
|
||||
/* The following data structures define the layout of a firmware binary
|
||||
* following the "PLDM For Firmware Update Specification", DMTF standard
|
||||
* #DSP0267.
|
||||
*
|
||||
* pldmfw.c uses these structures to implement a simple engine that will parse
|
||||
* a fw binary file in this format and perform a firmware update for a given
|
||||
* device.
|
||||
*
|
||||
* Due to the variable sized data layout, alignment of fields within these
|
||||
* structures is not guaranteed when reading. For this reason, all multi-byte
|
||||
* field accesses should be done using the unaligned access macros.
|
||||
* Additionally, the standard specifies that multi-byte fields are in
|
||||
* LittleEndian format.
|
||||
*
|
||||
* The structure definitions are not made public, in order to keep direct
|
||||
* accesses within code that is prepared to deal with the limitation of
|
||||
* unaligned access.
|
||||
*/
|
||||
|
||||
/* UUID for PLDM firmware packages: f018878c-cb7d-4943-9800-a02f059aca02 */
|
||||
static const uuid_t pldm_firmware_header_id =
|
||||
UUID_INIT(0xf018878c, 0xcb7d, 0x4943,
|
||||
0x98, 0x00, 0xa0, 0x2f, 0x05, 0x9a, 0xca, 0x02);
|
||||
|
||||
/* Revision number of the PLDM header format this code supports */
|
||||
// SIM_DEBUG
|
||||
#define PACKAGE_HEADER_FORMAT_REVISION 0x03
|
||||
#define COMPONENT_OPAQUE_DATA_LENGTH 4
|
||||
|
||||
/* timestamp104 structure defined in PLDM Base specification */
|
||||
#define PLDM_TIMESTAMP_SIZE 13
|
||||
struct __pldm_timestamp {
|
||||
u8 b[PLDM_TIMESTAMP_SIZE];
|
||||
} __packed __aligned(1);
|
||||
|
||||
/* Package Header Information */
|
||||
struct __pldm_header {
|
||||
uuid_t id; /* PackageHeaderIdentifier */
|
||||
u8 revision; /* PackageHeaderFormatRevision */
|
||||
__le16 size; /* PackageHeaderSize */
|
||||
struct __pldm_timestamp release_date; /* PackageReleaseDateTime */
|
||||
__le16 component_bitmap_len; /* ComponentBitmapBitLength */
|
||||
u8 version_type; /* PackageVersionStringType */
|
||||
u8 version_len; /* PackageVersionStringLength */
|
||||
|
||||
/*
|
||||
* DSP0267 also includes the following variable length fields at the
|
||||
* end of this structure:
|
||||
*
|
||||
* PackageVersionString, length is version_len.
|
||||
*
|
||||
* The total size of this section is
|
||||
* sizeof(pldm_header) + version_len;
|
||||
*/
|
||||
u8 version_string[]; /* PackageVersionString */
|
||||
} __packed __aligned(1);
|
||||
|
||||
/* Firmware Device ID Record */
|
||||
struct __pldmfw_record_info {
|
||||
__le16 record_len; /* RecordLength */
|
||||
u8 descriptor_count; /* DescriptorCount */
|
||||
__le32 device_update_flags; /* DeviceUpdateOptionFlags */
|
||||
u8 version_type; /* ComponentImageSetVersionType */
|
||||
u8 version_len; /* ComponentImageSetVersionLength */
|
||||
__le16 package_data_len; /* FirmwareDevicePackageDataLength */
|
||||
|
||||
/*
|
||||
* DSP0267 also includes the following variable length fields at the
|
||||
* end of this structure:
|
||||
*
|
||||
* ApplicableComponents, length is component_bitmap_len from header
|
||||
* ComponentImageSetVersionString, length is version_len
|
||||
* RecordDescriptors, a series of TLVs with 16bit type and length
|
||||
* FirmwareDevicePackageData, length is package_data_len
|
||||
*
|
||||
* The total size of each record is
|
||||
* sizeof(pldmfw_record_info) +
|
||||
* component_bitmap_len (converted to bytes!) +
|
||||
* version_len +
|
||||
* <length of RecordDescriptors> +
|
||||
* package_data_len
|
||||
*/
|
||||
u8 variable_record_data[];
|
||||
} __packed __aligned(1);
|
||||
|
||||
/* Firmware Descriptor Definition */
|
||||
struct __pldmfw_desc_tlv {
|
||||
__le16 type; /* DescriptorType */
|
||||
__le16 size; /* DescriptorSize */
|
||||
u8 data[]; /* DescriptorData */
|
||||
} __aligned(1);
|
||||
|
||||
/* Firmware Device Identification Area */
|
||||
struct __pldmfw_record_area {
|
||||
u8 record_count; /* DeviceIDRecordCount */
|
||||
/* This is not a struct type because the size of each record varies */
|
||||
u8 records[];
|
||||
} __aligned(1);
|
||||
|
||||
/* Individual Component Image Information */
|
||||
struct __pldmfw_component_info {
|
||||
__le16 classification; /* ComponentClassfication */
|
||||
__le16 identifier; /* ComponentIdentifier */
|
||||
__le32 comparison_stamp; /* ComponentComparisonStamp */
|
||||
__le16 options; /* componentOptions */
|
||||
__le16 activation_method; /* RequestedComponentActivationMethod */
|
||||
__le32 location_offset; /* ComponentLocationOffset */
|
||||
__le32 size; /* ComponentSize */
|
||||
u8 version_type; /* ComponentVersionStringType */
|
||||
u8 version_len; /* ComponentVersionStringLength */
|
||||
|
||||
/*
|
||||
* DSP0267 also includes the following variable length fields at the
|
||||
* end of this structure:
|
||||
*
|
||||
* ComponentVersionString, length is version_len
|
||||
*
|
||||
* The total size of this section is
|
||||
* sizeof(pldmfw_component_info) + version_len;
|
||||
*/
|
||||
u8 version_string[];
|
||||
} __packed __aligned(1);
|
||||
|
||||
/* Component Image Information Area */
|
||||
struct __pldmfw_component_area {
|
||||
__le16 component_image_count;
|
||||
/* This is not a struct type because the component size varies */
|
||||
u8 components[];
|
||||
} __aligned(1);
|
||||
|
||||
/**
|
||||
* pldm_first_desc_tlv
|
||||
* @start: byte offset of the start of the descriptor TLVs
|
||||
*
|
||||
* Converts the starting offset of the descriptor TLVs into a pointer to the
|
||||
* first descriptor.
|
||||
*/
|
||||
#define pldm_first_desc_tlv(start) \
|
||||
((const struct __pldmfw_desc_tlv *)(start))
|
||||
|
||||
/**
|
||||
* pldm_next_desc_tlv
|
||||
* @desc: pointer to a descriptor TLV
|
||||
*
|
||||
* Finds the pointer to the next descriptor following a given descriptor
|
||||
*/
|
||||
#define pldm_next_desc_tlv(desc) \
|
||||
((const struct __pldmfw_desc_tlv *)((desc)->data + \
|
||||
get_unaligned_le16(&(desc)->size)))
|
||||
|
||||
/**
|
||||
* pldm_for_each_desc_tlv
|
||||
* @i: variable to store descriptor index
|
||||
* @desc: variable to store descriptor pointer
|
||||
* @start: byte offset of the start of the descriptors
|
||||
* @count: the number of descriptors
|
||||
*
|
||||
* for loop macro to iterate over all of the descriptors of a given PLDM
|
||||
* record.
|
||||
*/
|
||||
#define pldm_for_each_desc_tlv(i, desc, start, count) \
|
||||
for ((i) = 0, (desc) = pldm_first_desc_tlv(start); \
|
||||
(i) < (count); \
|
||||
(i)++, (desc) = pldm_next_desc_tlv(desc))
|
||||
|
||||
/**
|
||||
* pldm_first_record
|
||||
* @start: byte offset of the start of the PLDM records
|
||||
*
|
||||
* Converts a starting offset of the PLDM records into a pointer to the first
|
||||
* record.
|
||||
*/
|
||||
#define pldm_first_record(start) \
|
||||
((const struct __pldmfw_record_info *)(start))
|
||||
|
||||
/**
|
||||
* pldm_next_record
|
||||
* @record: pointer to a PLDM record
|
||||
*
|
||||
* Finds a pointer to the next record following a given record
|
||||
*/
|
||||
#define pldm_next_record(record) \
|
||||
((const struct __pldmfw_record_info *) \
|
||||
((const u8 *)(record) + get_unaligned_le16(&(record)->record_len)))
|
||||
|
||||
/**
|
||||
* pldm_for_each_record
|
||||
* @i: variable to store record index
|
||||
* @record: variable to store record pointer
|
||||
* @start: byte offset of the start of the records
|
||||
* @count: the number of records
|
||||
*
|
||||
* for loop macro to iterate over all of the records of a PLDM file.
|
||||
*/
|
||||
#define pldm_for_each_record(i, record, start, count) \
|
||||
for ((i) = 0, (record) = pldm_first_record(start); \
|
||||
(i) < (count); \
|
||||
(i)++, (record) = pldm_next_record(record))
|
||||
|
||||
/**
|
||||
* pldm_first_component
|
||||
* @start: byte offset of the start of the PLDM components
|
||||
*
|
||||
* Convert a starting offset of the PLDM components into a pointer to the
|
||||
* first component
|
||||
*/
|
||||
#define pldm_first_component(start) \
|
||||
((const struct __pldmfw_component_info *)(start))
|
||||
|
||||
/**
|
||||
* pldm_next_component
|
||||
* @component: pointer to a PLDM component
|
||||
*
|
||||
* Finds a pointer to the next component following a given component
|
||||
*/
|
||||
#define pldm_next_component(component) \
|
||||
((const struct __pldmfw_component_info *)((component)->version_string + \
|
||||
(component)->version_len + COMPONENT_OPAQUE_DATA_LENGTH))
|
||||
|
||||
/**
|
||||
* pldm_for_each_component
|
||||
* @i: variable to store component index
|
||||
* @component: variable to store component pointer
|
||||
* @start: byte offset to the start of the first component
|
||||
* @count: the number of components
|
||||
*
|
||||
* for loop macro to iterate over all of the components of a PLDM file.
|
||||
*/
|
||||
#define pldm_for_each_component(i, component, start, count) \
|
||||
for ((i) = 0, (component) = pldm_first_component(start); \
|
||||
(i) < (count); \
|
||||
(i)++, (component) = pldm_next_component(component))
|
||||
|
||||
struct crete_pldmfw_priv {
|
||||
struct pldmfw *context;
|
||||
const struct firmware *fw;
|
||||
|
||||
/* current offset of firmware image */
|
||||
size_t offset;
|
||||
|
||||
struct list_head records;
|
||||
struct list_head components;
|
||||
|
||||
/* PLDM Firmware Package Header */
|
||||
const struct __pldm_header *header;
|
||||
u16 total_header_size;
|
||||
|
||||
/* length of the component bitmap */
|
||||
u16 component_bitmap_len;
|
||||
u16 bitmap_size;
|
||||
|
||||
/* Start of the component image information */
|
||||
u16 component_count;
|
||||
const u8 *component_start;
|
||||
|
||||
/* Start pf the firmware device id records */
|
||||
const u8 *record_start;
|
||||
u8 record_count;
|
||||
|
||||
/* The CRC at the end of the package header */
|
||||
u32 header_crc;
|
||||
|
||||
struct pldmfw_record *matching_record;
|
||||
};
|
||||
|
||||
|
||||
|
||||
int crete_pldm_parse_image(struct crete_pldmfw_priv *data);
|
||||
void crete_pldmfw_free_priv(struct crete_pldmfw_priv *data);
|
||||
|
||||
|
||||
#endif
|
@ -0,0 +1,95 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#include <linux/clocksource.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/ptp_clock_kernel.h>
|
||||
#include "crete.h"
|
||||
#include "crete_ptp.h"
|
||||
|
||||
static int crete_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
|
||||
{
|
||||
pr_warn("ptp %s stub\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int crete_ptp_adjphase(struct ptp_clock_info *ptp, s32 delta)
|
||||
{
|
||||
pr_warn("ptp %s stub\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int crete_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
|
||||
{
|
||||
pr_warn("ptp %s stub\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int crete_ptp_gettimex(struct ptp_clock_info *ptp, struct timespec64 *ts,
|
||||
struct ptp_system_timestamp *sts)
|
||||
{
|
||||
pr_warn("ptp %s stub\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
static int crete_ptp_settime(struct ptp_clock_info *ptp, const struct timespec64 *ts)
|
||||
{
|
||||
pr_warn("ptp %s stub\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static const struct ptp_clock_info crete_ptp_clock_info = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "crete_ptp",
|
||||
.max_adj = 50000000,
|
||||
.n_alarm = 0,
|
||||
.n_ext_ts = 0,
|
||||
.n_per_out = 0,
|
||||
.n_pins = 0,
|
||||
.pps = 0,
|
||||
.adjfine = crete_ptp_adjfine,
|
||||
.adjphase = crete_ptp_adjphase,
|
||||
.adjtime = crete_ptp_adjtime,
|
||||
.gettimex64 = crete_ptp_gettimex,
|
||||
.settime64 = crete_ptp_settime,
|
||||
.enable = NULL,
|
||||
.verify = NULL,
|
||||
};
|
||||
|
||||
void crete_init_clock(struct crete_core_dev *mdev)
|
||||
{
|
||||
pr_warn("ptp %s stub\n", __func__);
|
||||
}
|
||||
void crete_cleanup_clock(struct crete_core_dev *mdev)
|
||||
{
|
||||
pr_warn("ptp %s stub\n", __func__);
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __CRETE_PTP_H
|
||||
#define __CRETE_PTP_H
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/if_link.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/xarray.h>
|
||||
#include <net/devlink.h>
|
||||
#include <linux/net_tstamp.h>
|
||||
#include "crete_eswitch.h"
|
||||
|
||||
struct crete_clock {
|
||||
struct crete_nb pps_nb;
|
||||
seqlock_t lock;
|
||||
struct hwtstamp_config hwtstamp_config;
|
||||
struct ptp_clock *ptp;
|
||||
struct ptp_clock_info ptp_info;
|
||||
};
|
||||
void crete_init_clock(struct crete_core_dev *mdev);
|
||||
void crete_cleanup_clock(struct crete_core_dev *mdev);
|
||||
|
||||
|
||||
#endif /* __CRETE_PTP_H */
|
@ -0,0 +1,241 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#include "crete_rdma_adapt.h"
|
||||
#include "crete_rdma_dev.h"
|
||||
|
||||
#define RDMA_ERR(pdev, fmt, ...) dev_err(&pdev->dev, fmt, ##__VA_ARGS__)
|
||||
#define jm_core_dbg(pdev, format, ...) \
|
||||
dev_dbg(&pdev->dev, "%s:%d:(pid %d): " format, __func__, \
|
||||
__LINE__, current->pid, ##__VA_ARGS__)
|
||||
|
||||
#define TO_EQ_DB_VAL(ci, alt, v0, v1) \
|
||||
((((ci) & 0xffffff) << 2) | (((alt) ? (v0) : (v1)) & 0x3))
|
||||
|
||||
|
||||
static bool crete_rdma_is_error(struct jm_rdma_core *dev)
|
||||
{
|
||||
struct crete_core_dev *core_dev = container_of(dev, struct crete_core_dev, rdma_coredev);
|
||||
|
||||
if (!dev) {
|
||||
pr_err("rdma get irq err: dev is null\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return pci_channel_offline(core_dev->pdev);
|
||||
}
|
||||
|
||||
static void crete_rdma_trigger_doorbell(struct jm_rdma_core *dev, u32 event)
|
||||
{
|
||||
struct crete_core_dev *core_dev = container_of(dev, struct crete_core_dev, rdma_coredev);
|
||||
|
||||
if (!dev) {
|
||||
pr_err("rdma get irq err: dev is null\n");
|
||||
return;
|
||||
}
|
||||
jm_core_dbg(core_dev->pdev, "rdma db base addr:0x%p val:0x%x\r\n",
|
||||
core_dev->rdma_adp.cmd_db_reg, event);
|
||||
iowrite32(event, core_dev->rdma_adp.cmd_db_reg);
|
||||
}
|
||||
|
||||
|
||||
static int crete_rdma_get_irqn(struct jm_rdma_core *dev, int index)
|
||||
{
|
||||
struct crete_core_dev *core_dev = container_of(dev, struct crete_core_dev, rdma_coredev);
|
||||
int irq;
|
||||
|
||||
if (!dev) {
|
||||
pr_err("rdma get irq err: dev is null\n");
|
||||
goto ret;
|
||||
}
|
||||
if (index >= core_dev->rdma_adp.vector_num + core_dev->rdma_adp.vector_base) {
|
||||
pr_err("@@@@###index =%d >= num=%d vector_base=%d@@@@\n",
|
||||
index, core_dev->rdma_adp.vector_num, core_dev->rdma_adp.vector_base);
|
||||
goto ret;
|
||||
}
|
||||
|
||||
irq = core_dev->irq_info[index].vector;
|
||||
|
||||
jm_core_dbg(core_dev->pdev, "vector base = %d index = %d irqn =%d\n",
|
||||
core_dev->rdma_adp.vector_base, index, irq);
|
||||
return irq;
|
||||
ret:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
struct device *crete_rdma_get_device(struct jm_rdma_core *dev)
|
||||
{
|
||||
struct crete_core_dev *core_dev = container_of(dev, struct crete_core_dev, rdma_coredev);
|
||||
struct pci_dev *pdev = core_dev->pdev;
|
||||
|
||||
return &pdev->dev;
|
||||
}
|
||||
|
||||
void crete_rdma_get_dev_info(struct jm_rdma_core *dev, u8 *feature,
|
||||
u8 *rev_id, u16 *dev_id, u16 *vendor)
|
||||
{
|
||||
struct crete_core_dev *core_dev = container_of(dev, struct crete_core_dev, rdma_coredev);
|
||||
struct pci_dev *pdev = core_dev->pdev;
|
||||
|
||||
*rev_id = pdev->revision;
|
||||
*dev_id = pdev->device;
|
||||
*vendor = pdev->vendor;
|
||||
if (!pci_enable_atomic_ops_to_root(pdev, PCI_EXP_DEVCAP2_ATOMIC_COMP64))
|
||||
*feature = *feature | JM_DEVICE_FEATURE_ATOMIC_HCA;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void crete_rdma_get_bar(struct jm_rdma_core *dev, void **base, void **eq_reg)
|
||||
{
|
||||
struct crete_core_dev *core_dev = container_of(dev, struct crete_core_dev, rdma_coredev);
|
||||
|
||||
*base = core_dev->rdma_adp.reg_addr;
|
||||
*eq_reg = core_dev->rdma_adp.eq_db_reg;
|
||||
}
|
||||
|
||||
void crete_rdma_get_uar(struct jm_rdma_core *dev, phys_addr_t *base, int *len)
|
||||
{
|
||||
struct crete_core_dev *core_dev = container_of(dev, struct crete_core_dev, rdma_coredev);
|
||||
|
||||
*base = core_dev->rdma_adp.uar_base;
|
||||
*len = core_dev->rdma_adp.uar_size;
|
||||
}
|
||||
|
||||
void crete_rdma_get_vector(struct jm_rdma_core *dev, int *num, int *base)
|
||||
{
|
||||
struct crete_core_dev *core_dev = container_of(dev, struct crete_core_dev, rdma_coredev);
|
||||
|
||||
*num = core_dev->rdma_adp.vector_num;
|
||||
*base = core_dev->rdma_adp.vector_base;
|
||||
}
|
||||
|
||||
|
||||
static struct jm_rdma_ops jm_pci_core_ops = {
|
||||
.get_device = crete_rdma_get_device,
|
||||
.get_dev_info = crete_rdma_get_dev_info,
|
||||
.cmdq_notify = crete_rdma_trigger_doorbell,
|
||||
.get_irqn = crete_rdma_get_irqn,
|
||||
.store_bond_info = NULL,
|
||||
.get_bar = crete_rdma_get_bar,
|
||||
.get_uar = crete_rdma_get_uar,
|
||||
.get_vector = crete_rdma_get_vector,
|
||||
.is_error = crete_rdma_is_error,
|
||||
.timer_db = NULL,
|
||||
.reload = NULL,
|
||||
};
|
||||
|
||||
|
||||
int crete_rdma_init_core_dev(struct crete_core_dev *core_dev, struct pci_dev *pdev)
|
||||
{
|
||||
struct jm_rdma_core *dev;
|
||||
int ret = 0;
|
||||
|
||||
dev = &core_dev->rdma_coredev;
|
||||
|
||||
dev->ops = &jm_pci_core_ops;
|
||||
|
||||
mutex_init(&core_dev->rdma_adp.intf_state_mutex);
|
||||
ret = jm_adev_idx_alloc();
|
||||
if (ret < 0) {
|
||||
RDMA_ERR(pdev, "failed to initialize adev index\n");
|
||||
goto err_core_free;
|
||||
}
|
||||
dev->adev_idx = ret;
|
||||
ret = jm_adev_init(dev);
|
||||
if (ret < 0) {
|
||||
RDMA_ERR(pdev, "failed to initialize adev table\n");
|
||||
goto err_idx_free;
|
||||
}
|
||||
return 0;
|
||||
err_idx_free:
|
||||
jm_adev_idx_free(dev->adev_idx);
|
||||
err_core_free:
|
||||
mutex_destroy(&core_dev->rdma_adp.intf_state_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void crete_rdma_remove_core_dev(struct crete_core_dev *core_dev)
|
||||
{
|
||||
struct jm_rdma_core *dev;
|
||||
|
||||
dev = &core_dev->rdma_coredev;
|
||||
jm_adev_cleanup(dev);
|
||||
jm_adev_idx_free(dev->adev_idx);
|
||||
mutex_destroy(&core_dev->rdma_adp.intf_state_mutex);
|
||||
}
|
||||
|
||||
int crete_rdma_coredev_init(struct crete_core_dev *core_dev)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!crete_have_rdma_cap(core_dev)) {
|
||||
jm_core_dbg(core_dev->pdev, "not found rdma cap.\n");
|
||||
return 0;
|
||||
}
|
||||
core_dev->rdma_adp.flags |= CORSICA_RDMA_MASK;
|
||||
err = crete_rdma_init_core_dev(core_dev, core_dev->pdev);
|
||||
if (err)
|
||||
goto err_rdma_init_core_dev;
|
||||
|
||||
|
||||
core_dev->rdma_adp.reg_addr =
|
||||
core_dev->io_addr + core_dev->hw.rdma_desc.offset * CRETE_RDMA_OFFSET_UNIT;
|
||||
core_dev->rdma_adp.bar_offset = core_dev->hw.rdma_desc.offset * CRETE_RDMA_OFFSET_UNIT;
|
||||
core_dev->rdma_adp.bar_len = core_dev->hw.rdma_desc.len * CRETE_RDMA_OFFSET_UNIT;
|
||||
core_dev->rdma_adp.cmd_db_reg = core_dev->rdma_adp.reg_addr + JM_DEV_CMD_DB_OFFSET;
|
||||
core_dev->rdma_adp.eq_db_reg = core_dev->rdma_adp.reg_addr + JM_DEV_EQ_DB_OFFSET;
|
||||
core_dev->rdma_adp.uar_base =
|
||||
core_dev->bar_addr + core_dev->rdma_adp.bar_offset + JM_DEV_INIT_SEG_SIZE;
|
||||
core_dev->rdma_adp.uar_size = JM_DEV_UAR_SEG_SIZE;
|
||||
|
||||
jm_core_dbg(core_dev->pdev,
|
||||
"reg_addr =0x%p uar_base =0x%llx uar_size =0x%x bar=%d init_base=0x%llx offset=0x%x\n",
|
||||
core_dev->rdma_adp.reg_addr, core_dev->rdma_adp.uar_base,
|
||||
core_dev->rdma_adp.uar_size, JM_DEV_BAR_IDX, core_dev->bar_addr,
|
||||
core_dev->rdma_adp.bar_offset);
|
||||
return 0;
|
||||
|
||||
err_rdma_init_core_dev:
|
||||
crete_rdma_remove_core_dev(core_dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
void crete_rdma_coredev_uninit(struct crete_core_dev *core_dev)
|
||||
{
|
||||
if (!crete_have_rdma_cap(core_dev))
|
||||
return;
|
||||
|
||||
crete_rdma_remove_core_dev(core_dev);
|
||||
memset(&core_dev->rdma_coredev, 0, sizeof(core_dev->rdma_coredev));
|
||||
}
|
||||
|
@ -0,0 +1,64 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __CRETE_RDMA_CORE_ADAPT_H
|
||||
#define __CRETE_RDMA_CORE_ADAPT_H
|
||||
#include "crete.h"
|
||||
|
||||
#define JM_AUX_VECTOR_NUM 3
|
||||
|
||||
enum {
|
||||
JM_EQ_DB_FLAG_ARM = BIT(0),
|
||||
JM_EQ_DB_FLAG_COMP = BIT(1),
|
||||
};
|
||||
|
||||
enum {
|
||||
JM_PRIV_FLAGS_DISABLE_IB_ADEV = 1 << 0,
|
||||
JM_PRIV_FLAGS_DISABLE_ALL_ADEV = 1 << 1,
|
||||
JM_PRIV_FLAGS_DETACH = 1 << 2,
|
||||
};
|
||||
|
||||
enum {
|
||||
JM_DEV_BAR_IDX = 0,
|
||||
JM_DEV_INIT_SEG_SIZE = 64 * 1024,
|
||||
JM_DEV_CMD_DB_OFFSET = 0xEFC0,
|
||||
JM_DEV_EQ_DB_OFFSET = 0xF000,
|
||||
JM_DEV_UAR_SEG_SIZE = 64 * 1024,
|
||||
};
|
||||
|
||||
#define CRETE_RDMA_OFFSET_UNIT 0x1000
|
||||
int crete_rdma_coredev_init(struct crete_core_dev *core_dev);
|
||||
void crete_rdma_coredev_uninit(struct crete_core_dev *core_dev);
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,254 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
|
||||
/*
|
||||
* Copyright (c) 2022, Jaguarmicro Technologies, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/idr.h>
|
||||
#include <linux/slab.h>
|
||||
#include "crete_rdma_dev.h"
|
||||
#include "rdma.h"
|
||||
#include "crete_rdma_adapt.h"
|
||||
|
||||
/* intf dev list mutex */
|
||||
static DEFINE_MUTEX(jm_intf_mutex);
|
||||
static DEFINE_IDA(jm_adev_ida);
|
||||
|
||||
bool is_ib_supported(struct jm_rdma_core *dev)
|
||||
{
|
||||
struct crete_core_dev *core_dev = container_of(dev, struct crete_core_dev, rdma_coredev);
|
||||
|
||||
if (core_dev->rdma_adp.priv_flags & JM_PRIV_FLAGS_DISABLE_IB_ADEV)
|
||||
return false;
|
||||
if (!(core_dev->rdma_adp.flags & CORSICA_RDMA_MASK))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
enum {
|
||||
JM_INTERFACE_PROTOCOL_IB,
|
||||
};
|
||||
|
||||
|
||||
static const struct jm_adev_device {
|
||||
const char *suffix;
|
||||
bool (*is_supported)(struct jm_rdma_core *dev);
|
||||
} jm_adev_devices[] = {
|
||||
[JM_INTERFACE_PROTOCOL_IB] = { .suffix = "rdma",
|
||||
.is_supported = &is_ib_supported },
|
||||
};
|
||||
|
||||
|
||||
int jm_adev_idx_alloc(void)
|
||||
{
|
||||
return ida_alloc(&jm_adev_ida, GFP_KERNEL);
|
||||
}
|
||||
|
||||
void jm_adev_idx_free(int idx)
|
||||
{
|
||||
ida_free(&jm_adev_ida, idx);
|
||||
}
|
||||
|
||||
int jm_adev_init(struct jm_rdma_core *dev)
|
||||
{
|
||||
struct jm_rdma_adev **adev;
|
||||
|
||||
adev = kcalloc(ARRAY_SIZE(jm_adev_devices),
|
||||
sizeof(struct jm_rdma_adev *), GFP_KERNEL);
|
||||
if (!adev)
|
||||
return -ENOMEM;
|
||||
dev->adev = adev;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void jm_adev_cleanup(struct jm_rdma_core *dev)
|
||||
{
|
||||
kfree(dev->adev);
|
||||
}
|
||||
|
||||
static void adev_release(struct device *dev)
|
||||
{
|
||||
struct jm_rdma_adev *adev = container_of(dev, struct jm_rdma_adev, adev.dev);
|
||||
|
||||
struct jm_rdma_core *core = adev->rdma_core;
|
||||
int idx = adev->idx;
|
||||
|
||||
kfree(adev);
|
||||
core->adev[idx] = NULL;
|
||||
}
|
||||
|
||||
static struct jm_rdma_adev *add_adev(struct jm_rdma_core *dev, int idx)
|
||||
{
|
||||
struct crete_core_dev *core_dev = container_of(dev, struct crete_core_dev, rdma_coredev);
|
||||
const char *suffix = jm_adev_devices[idx].suffix;
|
||||
struct auxiliary_device *adev;
|
||||
struct jm_rdma_adev *jadev;
|
||||
int ret;
|
||||
|
||||
jadev = kzalloc(sizeof(*jadev), GFP_KERNEL);
|
||||
if (!jadev)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
adev = &jadev->adev;
|
||||
adev->id = dev->adev_idx;
|
||||
adev->name = suffix;
|
||||
adev->dev.parent = &core_dev->pdev->dev;
|
||||
adev->dev.release = adev_release;
|
||||
jadev->rdma_core = dev;
|
||||
jadev->idx = idx;
|
||||
ret = auxiliary_device_init(adev);
|
||||
if (ret) {
|
||||
kfree(jadev);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
ret = auxiliary_device_add(adev);
|
||||
if (ret) {
|
||||
auxiliary_device_uninit(adev);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
return jadev;
|
||||
}
|
||||
|
||||
static void del_adev(struct auxiliary_device *adev)
|
||||
{
|
||||
auxiliary_device_delete(adev);
|
||||
auxiliary_device_uninit(adev);
|
||||
}
|
||||
|
||||
|
||||
int jm_attach_device(struct jm_rdma_core *dev)
|
||||
{
|
||||
struct auxiliary_device *adev;
|
||||
struct auxiliary_driver *adrv;
|
||||
struct jm_rdma_adev **jadev = dev->adev;
|
||||
int ret = 0, i;
|
||||
struct crete_core_dev *core_dev = container_of(dev, struct crete_core_dev, rdma_coredev);
|
||||
|
||||
mutex_lock(&jm_intf_mutex);
|
||||
core_dev->rdma_adp.priv_flags &= ~JM_PRIV_FLAGS_DETACH;
|
||||
for (i = 0; i < ARRAY_SIZE(jm_adev_devices); i++) {
|
||||
if (!jadev[i]) {
|
||||
bool is_supported = false;
|
||||
|
||||
if (jm_adev_devices[i].is_supported)
|
||||
is_supported = jm_adev_devices[i].is_supported(dev);
|
||||
if (!is_supported)
|
||||
continue;
|
||||
jadev[i] = add_adev(dev, i);
|
||||
if (IS_ERR(jadev[i])) {
|
||||
ret = PTR_ERR(jadev[i]);
|
||||
jadev[i] = NULL;
|
||||
}
|
||||
} else {
|
||||
adev = &(jadev[i]->adev);
|
||||
if (!adev->dev.driver)
|
||||
continue;
|
||||
adrv = to_auxiliary_drv(adev->dev.driver);
|
||||
if (adrv->resume)
|
||||
ret = adrv->resume(adev);
|
||||
}
|
||||
if (ret) {
|
||||
pr_warn("Device[%d] (%s) failed to load\n",
|
||||
i, jm_adev_devices[i].suffix);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&jm_intf_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void jm_detach_device(struct jm_rdma_core *dev)
|
||||
{
|
||||
struct auxiliary_device *adev;
|
||||
struct auxiliary_driver *adrv;
|
||||
struct jm_rdma_adev **jadev = dev->adev;
|
||||
pm_message_t pm = {};
|
||||
struct crete_core_dev *core_dev = container_of(dev, struct crete_core_dev, rdma_coredev);
|
||||
int i;
|
||||
|
||||
if (!jadev) {
|
||||
pr_err("jnet adev null\n");
|
||||
return;
|
||||
}
|
||||
mutex_lock(&jm_intf_mutex);
|
||||
for (i = ARRAY_SIZE(jm_adev_devices) - 1; i >= 0; i--) {
|
||||
if (!jadev[i])
|
||||
continue;
|
||||
adev = &jadev[i]->adev;
|
||||
if (!adev->dev.driver) {
|
||||
pr_err("adev->dev.driver is null\n");
|
||||
goto skip_suspend;
|
||||
}
|
||||
adrv = to_auxiliary_drv(adev->dev.driver);
|
||||
if (adrv->suspend) {
|
||||
adrv->suspend(adev, pm);
|
||||
continue;
|
||||
}
|
||||
skip_suspend:
|
||||
del_adev(&jadev[i]->adev);
|
||||
jadev[i] = NULL;
|
||||
}
|
||||
core_dev->rdma_adp.priv_flags |= JM_PRIV_FLAGS_DETACH;
|
||||
mutex_unlock(&jm_intf_mutex);
|
||||
}
|
||||
|
||||
static int add_drivers(struct jm_rdma_core *dev)
|
||||
{
|
||||
int i, ret = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(jm_adev_devices); i++) {
|
||||
bool is_supported = false;
|
||||
|
||||
if (dev->adev[i])
|
||||
continue;
|
||||
if (jm_adev_devices[i].is_supported)
|
||||
is_supported = jm_adev_devices[i].is_supported(dev);
|
||||
if (!is_supported)
|
||||
continue;
|
||||
dev->adev[i] = add_adev(dev, i);
|
||||
if (IS_ERR(dev->adev[i])) {
|
||||
pr_warn("Device[%d] (%s) failed to load\n", i,
|
||||
jm_adev_devices[i].suffix);
|
||||
ret = PTR_ERR(dev->adev[i]);
|
||||
dev->adev[i] = NULL;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void delete_drivers(struct jm_rdma_core *dev)
|
||||
{
|
||||
struct crete_core_dev *core_dev = container_of(dev, struct crete_core_dev, rdma_coredev);
|
||||
bool delete_all;
|
||||
int i;
|
||||
|
||||
delete_all = core_dev->rdma_adp.priv_flags & JM_PRIV_FLAGS_DISABLE_ALL_ADEV;
|
||||
for (i = ARRAY_SIZE(jm_adev_devices) - 1; i >= 0; i--) {
|
||||
bool is_supported = false;
|
||||
|
||||
if (!dev->adev[i])
|
||||
continue;
|
||||
if (jm_adev_devices[i].is_supported && !delete_all)
|
||||
is_supported = jm_adev_devices[i].is_supported(dev);
|
||||
if (is_supported)
|
||||
continue;
|
||||
del_adev(&dev->adev[i]->adev);
|
||||
dev->adev[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int jm_rescan_drivers_locked(struct jm_rdma_core *dev)
|
||||
{
|
||||
struct crete_core_dev *core_dev = container_of(dev, struct crete_core_dev, rdma_coredev);
|
||||
|
||||
lockdep_assert_held(&jm_intf_mutex);
|
||||
if (core_dev->rdma_adp.priv_flags & JM_PRIV_FLAGS_DETACH)
|
||||
return 0;
|
||||
delete_drivers(dev);
|
||||
if (core_dev->rdma_adp.priv_flags & JM_PRIV_FLAGS_DISABLE_ALL_ADEV)
|
||||
return 0;
|
||||
return add_drivers(dev);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,49 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only*/
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __CRETE_RDMA_DEV_H
|
||||
#define __CRETE_RDMA_DEV_H
|
||||
#include "rdma.h"
|
||||
enum {
|
||||
CORSICA_RDMA_MASK = 1 << 4,
|
||||
};
|
||||
|
||||
int jm_adev_idx_alloc(void);
|
||||
void jm_adev_idx_free(int idx);
|
||||
int jm_adev_init(struct jm_rdma_core *dev);
|
||||
bool is_ib_supported(struct jm_rdma_core *dev);
|
||||
void jm_adev_cleanup(struct jm_rdma_core *dev);
|
||||
int jm_attach_device(struct jm_rdma_core *dev);
|
||||
void jm_detach_device(struct jm_rdma_core *dev);
|
||||
int jm_rescan_drivers_locked(struct jm_rdma_core *dev);
|
||||
#endif
|
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _CRETE_REGS_H
|
||||
#define _CRETE_REGS_H
|
||||
|
||||
#include "crete.h"
|
||||
#include <uapi/linux/stddef.h>
|
||||
|
||||
|
||||
/* Additional Transmit Descriptor Control definitions */
|
||||
#define CRETE_TXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Tx Queue */
|
||||
#define CRETE_RXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Tx Queue */
|
||||
|
||||
#define CRETE_TCTL_EN 0x00000002
|
||||
#define CRETE_RCTL_EN 0x00000002
|
||||
|
||||
#define CRETE_TCTL 0x100
|
||||
#define CRETE_RCTL 0x400
|
||||
|
||||
#define CRETE_TXDCTL(n) (0x1000 + ((n) * 0x100))
|
||||
#define CRETE_RXDCTL(n) (0x2000 + ((n) * 0x100))
|
||||
|
||||
#define CRETE_TDLEN(n) (0x1004 + ((n) * 0x100))
|
||||
#define CRETE_RDLEN(n) (0x2004 + ((n) * 0x100))
|
||||
|
||||
#define CRETE_TD_LO(n) (0x1008 + ((n) * 0x100))
|
||||
#define CRETE_TD_HI(n) (0x100c + ((n) * 0x100))
|
||||
|
||||
#define CRETE_RD_LO(n) (0x2008 + ((n) * 0x100))
|
||||
#define CRETE_RD_HI(n) (0x200c + ((n) * 0x100))
|
||||
|
||||
#define CRETE_TDH(n) (0x1010 + ((n) * 0x100))
|
||||
#define CRETE_RDH(n) (0x2010 + (n) * 0x100)
|
||||
|
||||
#define CRETE_TDT(n) (0x1014 + ((n) * 0x100))
|
||||
#define CRETE_RDT(n) (0x2014 + ((n) * 0x100))
|
||||
|
||||
#define CRETE_INTR(n) (0x3000 + ((n) * 0x10))
|
||||
|
||||
/* reg bits */
|
||||
#define CRETE_HW_RESET_OK 0
|
||||
#define CRETE_HW_RESET 1
|
||||
#define CRETE_HW_RESET_TIMEOUT 10
|
||||
|
||||
/* dev status */
|
||||
#define CRETE_DEV_ACK BIT(0)
|
||||
#define CRETE_DEV_DRV BIT(1)
|
||||
#define CRETE_DEV_CAP BIT(2)
|
||||
#define CRETE_DEV_CP BIT(3)
|
||||
#define CRETE_DEV_FAIL BIT(7)
|
||||
#define CRETE_DEV_OK 0
|
||||
#define POLL_RETRY_LIMIT 5
|
||||
|
||||
/* cp caps */
|
||||
#define CRETE_CP_CMDPATH BIT(0)
|
||||
#define CRETE_CP_ADQ BIT(1)
|
||||
#define CRETE_CP_EP BIT(2)
|
||||
#define CRETE_CP_CQ_EP BIT(3)
|
||||
|
||||
/*reg ops*/
|
||||
//#define wr32(p, reg, val) crete_wr32(p, reg, val)
|
||||
#ifdef __compiler_offsetof
|
||||
#define reg_off(TYPE, MEMBER) __compiler_offsetof(TYPE, MEMBER)
|
||||
#else
|
||||
#define reg_off(TYPE, MEMBER) ((size_t) &(((TYPE *)0)->MEMBER))
|
||||
#endif
|
||||
|
||||
#define rd32(p, reg) crete_rd32(p, reg)
|
||||
#define wr32(reg, val) \
|
||||
do { \
|
||||
u8 __iomem *hw_addr = READ_ONCE(adapter->io_addr); \
|
||||
writel((val), &hw_addr[(reg)]); \
|
||||
} while (0)
|
||||
|
||||
#define iseg_rd32(hw,type, mem) \
|
||||
do { \
|
||||
u8 __iomem *hw_addr = (u8 __iomem *)READ_ONCE(hw->io_addr); \
|
||||
return readl(hw_addr + reg_off(type, mem)); \
|
||||
} while (0)
|
||||
|
||||
/* maybe too complex */
|
||||
#define iseg_wd32(hw, type, mem, val) \
|
||||
do { \
|
||||
u8 __iomem *hw_addr = (u8 __iomem *)READ_ONCE((hw)->io_addr); \
|
||||
writel((val), hw_addr + reg_off(type, mem)); \
|
||||
} while (0)
|
||||
|
||||
#define iseg_rd8(hw,type, mem) \
|
||||
do { \
|
||||
u8 __iomem *hw_addr = (u8 __iomem *)READ_ONCE(hw->io_addr); \
|
||||
return readb(hw_addr + reg_off(type, mem)); \
|
||||
} while (0)
|
||||
|
||||
#define iseg_wd8(hw, type, mem, val) \
|
||||
do { \
|
||||
u8 __iomem *hw_addr = (u8 __iomem *)READ_ONCE(hw->io_addr); \
|
||||
writeb((val), hw_addr + reg_off(type, mem)); \
|
||||
} while (0)
|
||||
|
||||
#define POLL_CTRL_PATH_STATUS(hw, bit, cdev, err) \
|
||||
do { \
|
||||
int retry = POLL_RETRY_LIMIT; \
|
||||
while (!(val = readb(&(hw)->io_addr->cp_status) & (bit)) && retry) { \
|
||||
(retry)--; \
|
||||
mdelay(10); \
|
||||
crete_err((cdev)->device, "device crtl path not ready\n"); \
|
||||
} \
|
||||
if (retry == 0) { \
|
||||
(err) = -EBUSY; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static inline void hexdump(const unsigned char *buf, unsigned short len)
|
||||
{
|
||||
print_hex_dump(KERN_ERR," data: ", DUMP_PREFIX_NONE, 16, 1, buf, len, true);
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,263 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#include <linux/pci.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/jhash.h>
|
||||
#include <net/pkt_cls.h>
|
||||
#include "crete.h"
|
||||
|
||||
u16 crete_xmit_get_sfiinfo(struct sk_buff *skb)
|
||||
{
|
||||
struct metadata_dst *dst = skb_metadata_dst(skb);
|
||||
|
||||
if (!dst || dst->type != METADATA_HW_PORT_MUX)
|
||||
return CRETE_MAX_CFA_CODE;
|
||||
|
||||
return dst->u.port_info.port_id;
|
||||
}
|
||||
|
||||
struct net_device *crete_get_vf_rep(struct crete_core_dev *cdev, u16 cfa_code)
|
||||
{
|
||||
u16 vf_idx;
|
||||
u16 *cfa_code_map = cdev->eswitch->eswoffloads.cfa_code_map;
|
||||
struct crete_esw_rep *rep;
|
||||
|
||||
if (cfa_code && cfa_code_map) {
|
||||
vf_idx = cfa_code_map[cfa_code];
|
||||
if (vf_idx != CRETE_MAX_CFA_CODE) {
|
||||
rep =
|
||||
xa_load(&cdev->eswitch->eswoffloads.vport_reps,
|
||||
vf_idx);
|
||||
if (rep)
|
||||
return rep->dev;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void crete_vf_rep_rx(struct crete_core_dev *cdev, struct sk_buff *skb)
|
||||
{
|
||||
struct crete_priv *priv = netdev_priv(skb->dev);
|
||||
struct crete_esw_rep *vf_rep = priv->rep;
|
||||
|
||||
vf_rep->rx_stats.bytes += skb->len;
|
||||
vf_rep->rx_stats.packets++;
|
||||
|
||||
netif_receive_skb(skb);
|
||||
}
|
||||
|
||||
static const struct ethtool_ops crete_vf_rep_ethtool_ops = {
|
||||
.get_drvinfo = NULL
|
||||
};
|
||||
|
||||
static int crete_vf_rep_setup_tc(struct net_device *dev,
|
||||
enum tc_setup_type type, void *type_data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
crete_vf_rep_get_stats64(struct net_device *dev,
|
||||
struct rtnl_link_stats64 *stats)
|
||||
{
|
||||
struct crete_priv *priv = netdev_priv(dev);
|
||||
struct crete_esw_rep *vf_rep = priv->rep;
|
||||
|
||||
stats->rx_packets = vf_rep->rx_stats.packets;
|
||||
stats->rx_bytes = vf_rep->rx_stats.bytes;
|
||||
stats->tx_packets = vf_rep->tx_stats.packets;
|
||||
stats->tx_bytes = vf_rep->tx_stats.bytes;
|
||||
}
|
||||
|
||||
static int crete_vf_rep_open(struct net_device *dev)
|
||||
{
|
||||
struct crete_priv *priv = netdev_priv(dev);
|
||||
struct crete_core_dev *cdev = priv->coredev;
|
||||
|
||||
/*
|
||||
* with pf netdevice running
|
||||
* enable the rep netdevice
|
||||
*/
|
||||
if (netif_running(cdev->netdev)) {
|
||||
netif_carrier_on(dev);
|
||||
netif_tx_start_all_queues(dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int crete_vf_rep_close(struct net_device *dev)
|
||||
{
|
||||
netif_carrier_off(dev);
|
||||
netif_tx_disable(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static netdev_tx_t crete_vf_rep_xmit(struct sk_buff *skb,
|
||||
struct net_device *dev)
|
||||
{
|
||||
struct crete_priv *priv = netdev_priv(dev);
|
||||
struct crete_esw_rep *vf_rep = priv->rep;
|
||||
int err, len = skb->len;
|
||||
|
||||
/*
|
||||
* drop the skb _skb_refdst
|
||||
*/
|
||||
skb_dst_drop(skb);
|
||||
dst_hold((struct dst_entry *)vf_rep->dst);
|
||||
/*
|
||||
* redirection the skb dst with the rep dst info
|
||||
*/
|
||||
skb_dst_set(skb, (struct dst_entry *)vf_rep->dst);
|
||||
/* skb reuse the pf netdevice */
|
||||
skb->dev = vf_rep->dst->u.port_info.lower_dev;
|
||||
|
||||
err = dev_queue_xmit(skb);
|
||||
if (!err) {
|
||||
vf_rep->tx_stats.bytes += len;
|
||||
vf_rep->tx_stats.packets++;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static const struct net_device_ops crete_vf_rep_netdev_ops = {
|
||||
.ndo_open = crete_vf_rep_open,
|
||||
.ndo_stop = crete_vf_rep_close,
|
||||
.ndo_start_xmit = crete_vf_rep_xmit,
|
||||
.ndo_get_stats64 = crete_vf_rep_get_stats64,
|
||||
.ndo_setup_tc = crete_vf_rep_setup_tc,
|
||||
};
|
||||
|
||||
int crete_alloc_vf_rep_load(struct crete_core_dev *cdev,
|
||||
struct crete_esw_rep *rep)
|
||||
{
|
||||
struct crete_eswitch *esw = rep->esw;
|
||||
u16 *cfa_code_map = esw->eswoffloads.cfa_code_map;
|
||||
struct net_device *dev;
|
||||
struct net_device *pf_dev = cdev->netdev;
|
||||
struct crete_priv *priv;
|
||||
u16 sfi_code = 0;
|
||||
int err;
|
||||
|
||||
dev = alloc_etherdev(sizeof(*priv));
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
|
||||
priv = netdev_priv(dev);
|
||||
priv->coredev = cdev;
|
||||
priv->netdev = dev;
|
||||
priv->rep = rep;
|
||||
|
||||
/* alloc sfi code from FW */
|
||||
//crete_request_sfiinfo(cdev);
|
||||
rep->sfi_code = sfi_code;
|
||||
/* cfa code hash map */
|
||||
// cfa_code_map[rep->vport_idx] = sfi_code;
|
||||
cfa_code_map[sfi_code] = rep->vport_idx;
|
||||
/*
|
||||
* alloc hw port mux metadata used for rep
|
||||
* tx and rx function
|
||||
*/
|
||||
rep->dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX, GFP_KERNEL);
|
||||
if (!rep->dst) {
|
||||
err = -ENOMEM;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
rep->dst->u.port_info.port_id = rep->sfi_code;
|
||||
rep->dst->u.port_info.lower_dev = cdev->netdev;
|
||||
|
||||
dev->netdev_ops = &crete_vf_rep_netdev_ops;
|
||||
dev->ethtool_ops = &crete_vf_rep_ethtool_ops;
|
||||
dev->hw_features = pf_dev->hw_features;
|
||||
dev->gso_partial_features = pf_dev->gso_partial_features;
|
||||
dev->vlan_features = pf_dev->vlan_features;
|
||||
dev->hw_enc_features = pf_dev->hw_enc_features;
|
||||
dev->features |= pf_dev->features;
|
||||
/*
|
||||
* rep net device use the random mac address
|
||||
* vf rep random mac address
|
||||
*/
|
||||
eth_hw_addr_random(dev);
|
||||
/*
|
||||
* ********* please notice here **********
|
||||
* vf rep mtu need to ref the vf function
|
||||
*/
|
||||
dev->min_mtu = ETH_MIN_MTU;
|
||||
dev->max_mtu = MAX_STD_JUMBO_FRAME_SIZE;
|
||||
|
||||
err = register_netdev(dev);
|
||||
if (err)
|
||||
goto err2;
|
||||
|
||||
rep->dev = dev;
|
||||
|
||||
err2:
|
||||
dst_release((struct dst_entry *)rep->dst);
|
||||
rep->dst = NULL;
|
||||
|
||||
err1:
|
||||
free_netdev(dev);
|
||||
|
||||
return err;
|
||||
|
||||
}
|
||||
|
||||
void crete_alloc_vf_rep_unload(struct crete_core_dev *cdev,
|
||||
struct crete_esw_rep *rep)
|
||||
{
|
||||
struct net_device *dev = rep->dev;
|
||||
struct crete_eswitch *esw = cdev->eswitch;
|
||||
u16 *cfa_code_map = esw->eswoffloads.cfa_code_map;
|
||||
|
||||
if (netif_running(dev))
|
||||
crete_vf_rep_close(dev);
|
||||
|
||||
cfa_code_map[rep->vport_idx] = CRETE_MAX_CFA_CODE;
|
||||
|
||||
synchronize_net();
|
||||
|
||||
dst_release((struct dst_entry *)rep->dst);
|
||||
rep->dst = NULL;
|
||||
rep->sfi_code = CRETE_MAX_CFA_CODE;
|
||||
unregister_netdev(dev);
|
||||
free_netdev(dev);
|
||||
|
||||
rep->dev = NULL;
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __CRETE_REP
|
||||
#define __CRETE_REP
|
||||
|
||||
u16 crete_xmit_get_sfiinfo(struct sk_buff *skb);
|
||||
struct net_device *crete_get_vf_rep(struct crete_core_dev *cdev, u16 cfa_code);
|
||||
void crete_vf_rep_rx(struct crete_core_dev *cdev, struct sk_buff *skb);
|
||||
int crete_alloc_vf_rep_load(struct crete_core_dev *cdev,
|
||||
struct crete_esw_rep *rep);
|
||||
void crete_alloc_vf_rep_unload(struct crete_core_dev *cdev,
|
||||
struct crete_esw_rep *rep);
|
||||
|
||||
#endif
|
@ -0,0 +1,611 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include "crete.h"
|
||||
#include "crete_sriov.h"
|
||||
#include "crete_eswitch.h"
|
||||
#include "crete_sriov_sysfs.h"
|
||||
|
||||
static int crete_set_vf_attr(struct crete_core_dev *core_dev, int num_vfs)
|
||||
{
|
||||
int i;
|
||||
struct crete_vf_info *vf;
|
||||
|
||||
for (i = 0; i < num_vfs; i++) {
|
||||
vf = &core_dev->pf.vf[i];
|
||||
memset(vf, 0, sizeof(*vf));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int crete_alloc_vf_resources(struct crete_core_dev *core_dev, int num_vfs)
|
||||
{
|
||||
core_dev->pf.vf = kcalloc(num_vfs, sizeof(struct crete_vf_info), GFP_KERNEL);
|
||||
if (!core_dev->pf.vf)
|
||||
return -ENOMEM;
|
||||
|
||||
crete_set_vf_attr(core_dev, num_vfs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void crete_free_vf_resources(struct crete_core_dev *core_dev)
|
||||
{
|
||||
core_dev->pf.active_vfs = 0;
|
||||
kfree(core_dev->pf.vf);
|
||||
core_dev->pf.vf = NULL;
|
||||
}
|
||||
|
||||
static u16 crete_get_max_vfs(struct crete_core_dev *core_dev)
|
||||
{
|
||||
return pci_sriov_get_totalvfs(core_dev->pdev);
|
||||
}
|
||||
|
||||
int crete_get_func_caps(struct crete_core_dev *core_dev)
|
||||
{
|
||||
struct crete_pf_info *pf = &core_dev->pf;
|
||||
struct crete_vf_info *vf = &core_dev->vf;
|
||||
|
||||
if (crete_core_is_pf(core_dev)) {
|
||||
pf->fw_fid = 0;
|
||||
pf->port_id = 0;
|
||||
pf->first_vf_id = 0;
|
||||
pf->max_vfs = crete_get_max_vfs(core_dev);
|
||||
/* pf mac */
|
||||
} else if (crete_core_is_vf(core_dev)) {
|
||||
vf->fw_fid = 0;
|
||||
/* vf mac */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(crete_get_func_caps);
|
||||
|
||||
int crete_sriov_init(struct crete_core_dev *core_dev)
|
||||
{
|
||||
struct pci_dev *pdev = core_dev->pdev;
|
||||
int err;
|
||||
|
||||
if (!crete_core_is_pf(core_dev))
|
||||
return 0;
|
||||
|
||||
core_dev->pf.max_vfs = crete_get_max_vfs(core_dev);
|
||||
core_dev->pf.active_vfs = pci_num_vf(pdev);
|
||||
err = crete_sriov_sysfs_init(core_dev);
|
||||
if (err) {
|
||||
pr_err("failed to init SRIOV sysfs (%d)\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
void crete_sriov_cleanup(struct crete_core_dev *dev)
|
||||
{
|
||||
if (!crete_core_is_pf(dev))
|
||||
return;
|
||||
crete_sriov_sysfs_cleanup(dev);
|
||||
}
|
||||
|
||||
static int crete_device_enable_sriov(struct crete_core_dev *core_dev, int num_vfs)
|
||||
{
|
||||
struct crete_pf_info *pf = &core_dev->pf;
|
||||
int vf_id;
|
||||
int rc;
|
||||
rc = crete_eswitch_enable(core_dev->eswitch, num_vfs);
|
||||
if (rc) {
|
||||
pr_err("failed to enable eswitch SRIOV (%d)\n", rc);
|
||||
return rc;
|
||||
}
|
||||
rc = crete_alloc_vf_resources(core_dev, num_vfs);
|
||||
if (rc)
|
||||
goto err_crete_alloc_vf_resources;
|
||||
|
||||
for (vf_id = 0; vf_id < num_vfs; vf_id++) {
|
||||
pf->vf[vf_id].enabled = 1;
|
||||
pr_info("successfully enabled VF%d\n", vf_id);
|
||||
}
|
||||
rc = crete_create_vfs_sysfs(core_dev, num_vfs);
|
||||
if (rc) {
|
||||
pr_err("failed to create SRIOV sysfs (%d)\n", rc);
|
||||
goto err_crete_crete_vfs_sysfs;
|
||||
}
|
||||
core_dev->sriov_cfg = 1;
|
||||
|
||||
return 0;
|
||||
err_crete_crete_vfs_sysfs:
|
||||
for (vf_id = num_vfs - 1; vf_id >= 0; vf_id--) {
|
||||
if (!pf->vf[vf_id].enabled)
|
||||
continue;
|
||||
pf->vf[vf_id].enabled = 0;
|
||||
}
|
||||
crete_free_vf_resources(core_dev);
|
||||
err_crete_alloc_vf_resources:
|
||||
core_dev->sriov_cfg = 0;
|
||||
crete_eswitch_disable_sriov(core_dev->eswitch, true);
|
||||
return rc;
|
||||
}
|
||||
|
||||
void
|
||||
crete_device_disable_sriov(struct crete_core_dev *core_dev, int num_vfs, bool clear_vf)
|
||||
{
|
||||
struct crete_pf_info *pf = &core_dev->pf;
|
||||
int vf_id;
|
||||
|
||||
crete_destroy_vfs_sysfs(core_dev, num_vfs);
|
||||
for (vf_id = num_vfs - 1; vf_id >= 0; vf_id--) {
|
||||
if (!pf->vf[vf_id].enabled)
|
||||
continue;
|
||||
pf->vf[vf_id].enabled = 0;
|
||||
pr_info("successfully disabled VF%d\n", vf_id);
|
||||
}
|
||||
crete_free_vf_resources(core_dev);
|
||||
core_dev->sriov_cfg = 0;
|
||||
crete_eswitch_disable_sriov(core_dev->eswitch, clear_vf);
|
||||
}
|
||||
|
||||
|
||||
static int crete_sriov_enable(struct pci_dev *pdev, int num_vfs)
|
||||
{
|
||||
struct crete_core_dev *core_dev = pci_get_drvdata(pdev);
|
||||
int err;
|
||||
|
||||
err = crete_device_enable_sriov(core_dev, num_vfs);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "crete_device_enable_sriov failed : %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = pci_enable_sriov(pdev, num_vfs);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "pci_enable_sriov failed : %d\n", err);
|
||||
crete_device_disable_sriov(core_dev, num_vfs, true);
|
||||
}
|
||||
return err;
|
||||
|
||||
}
|
||||
|
||||
void crete_sriov_disable(struct pci_dev *pdev)
|
||||
{
|
||||
struct crete_core_dev *core_dev = pci_get_drvdata(pdev);
|
||||
|
||||
int num_vfs = pci_num_vf(core_dev->pdev);
|
||||
|
||||
pci_disable_sriov(pdev);
|
||||
crete_device_disable_sriov(core_dev, num_vfs, true);
|
||||
|
||||
}
|
||||
|
||||
int crete_pci_sriov_configure(struct pci_dev *pdev, int num_vfs)
|
||||
{
|
||||
struct crete_core_dev *core_dev = pci_get_drvdata(pdev);
|
||||
int err = 0;
|
||||
|
||||
if (num_vfs)
|
||||
err = crete_sriov_enable(pdev, num_vfs);
|
||||
else
|
||||
crete_sriov_disable(pdev);
|
||||
|
||||
if (!err)
|
||||
core_dev->pf.active_vfs = num_vfs;
|
||||
return err ? err : num_vfs;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int crete_vf_ndo_prep(struct net_device *netdev, int vf_id)
|
||||
{
|
||||
struct crete_priv *priv = netdev_priv(netdev);
|
||||
struct crete_core_dev *core_dev = priv->coredev;
|
||||
struct pci_dev *pdev = core_dev->pdev;
|
||||
struct crete_pf_info pf = core_dev->pf;
|
||||
|
||||
if (!pf.active_vfs) {
|
||||
dev_err(&pdev->dev, "vf ndo called though sriov is disabled\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (vf_id >= pf.active_vfs) {
|
||||
dev_err(&pdev->dev, "Invalid VF id %d\n", vf_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool crete_is_trusted_vf(struct net_device *netdev, struct crete_vf_info *vf)
|
||||
{
|
||||
struct crete_priv *priv = netdev_priv(netdev);
|
||||
struct crete_core_dev *core_dev = priv->coredev;
|
||||
struct pci_dev *pdev = core_dev->pdev;
|
||||
|
||||
if (crete_core_is_pf(core_dev))
|
||||
return !!(vf->flags & CRETE_VF_TRUST);
|
||||
|
||||
dev_err(&pdev->dev, "VF trust %s\n",
|
||||
!!(vf->func_qcfg_flags & FUNC_QCFG_RESP_FLAGS_TRUSTED_VF) ? "ON":"OFF");
|
||||
|
||||
//bnxt_hwrm_func_qcfg_flags(bp, vf);
|
||||
return !!(vf->func_qcfg_flags & FUNC_QCFG_RESP_FLAGS_TRUSTED_VF);
|
||||
}
|
||||
|
||||
|
||||
int crete_get_vf_config(struct net_device *netdev, int vf_id, struct ifla_vf_info *ivi)
|
||||
{
|
||||
int rc;
|
||||
struct crete_vf_info *vf;
|
||||
struct crete_priv *priv = netdev_priv(netdev);
|
||||
struct crete_core_dev *core_dev = priv->coredev;
|
||||
struct pci_dev *pdev = core_dev->pdev;
|
||||
struct crete_pf_info pf = core_dev->pf;
|
||||
|
||||
dev_err(&pdev->dev, "get VF:%d config", vf_id);
|
||||
|
||||
rc = crete_vf_ndo_prep(netdev, vf_id);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
ivi->vf = vf_id;
|
||||
vf = &pf.vf[vf_id];
|
||||
|
||||
if (is_valid_ether_addr(vf->mac_addr))
|
||||
memcpy(&ivi->mac, vf->mac_addr, ETH_ALEN);
|
||||
else
|
||||
memcpy(&ivi->mac, vf->vf_mac_addr, ETH_ALEN);
|
||||
ivi->max_tx_rate = vf->max_tx_rate;
|
||||
ivi->min_tx_rate = vf->min_tx_rate;
|
||||
ivi->vlan = vf->vlan;
|
||||
if (vf->flags & CRETE_VF_QOS)
|
||||
ivi->qos = vf->vlan >> VLAN_PRIO_SHIFT;
|
||||
else
|
||||
ivi->qos = 0;
|
||||
ivi->spoofchk = !!(vf->flags & CRETE_VF_SPOOFCHK);
|
||||
ivi->trusted = crete_is_trusted_vf(netdev, vf);
|
||||
if (!(vf->flags & CRETE_VF_LINK_FORCED))
|
||||
ivi->linkstate = IFLA_VF_LINK_STATE_AUTO;
|
||||
else if (vf->flags & CRETE_VF_LINK_UP)
|
||||
ivi->linkstate = IFLA_VF_LINK_STATE_ENABLE;
|
||||
else
|
||||
ivi->linkstate = IFLA_VF_LINK_STATE_DISABLE;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
*Setting the MAC Address for a VF
|
||||
*To change the MAC address for the specified VF:
|
||||
*# ip link set <ethX> vf 0 mac <address>
|
||||
*For example:
|
||||
*# ip link set <ethX> vf 0 mac 00:01:02:03:04:05
|
||||
*This setting lasts until the PF is reloaded.
|
||||
*NOTE: For untrusted VFs, assigning a MAC address for a VF from the host will
|
||||
*disable any subsequent requests to change the MAC address from within the VM.
|
||||
*This is a security feature. The VM is not aware of this restriction, so if this
|
||||
*is attempted in the VM, it will trigger MDD events. Trusted VFs are allowed to
|
||||
*change the MAC address from within the VM.
|
||||
*/
|
||||
int crete_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
|
||||
{
|
||||
int rc;
|
||||
struct crete_vf_info *vf;
|
||||
struct crete_priv *priv = netdev_priv(netdev);
|
||||
struct crete_core_dev *core_dev = priv->coredev;
|
||||
struct pci_dev *pdev = core_dev->pdev;
|
||||
struct crete_pf_info pf = core_dev->pf;
|
||||
|
||||
rc = crete_vf_ndo_prep(netdev, vf_id);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
vf = &pf.vf[vf_id];
|
||||
dev_err(&pdev->dev, "Set VF MAC VF id %d mac:%2x-%2x-%2x-%2x-%2x-%2x\n",
|
||||
vf_id, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
memcpy(vf->mac_addr, mac, ETH_ALEN);
|
||||
|
||||
return crete_eswitch_set_vport_mac(core_dev->eswitch, VPORT(vf_id), vf->mac_addr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Configuring VLAN Tagging on SR-IOV Enabled Adapter Ports
|
||||
*To configure VLAN tagging for the ports on an SR-IOV enabled adapter, use the
|
||||
*following command. The VLAN configuration should be done before the VM is booted.
|
||||
*The VF is not aware of the VLAN tag being
|
||||
*inserted on transmit and removed on received frames (sometimes called "port
|
||||
*VLAN" mode).
|
||||
*# ip link set dev <ethX> vf <id> vlan <vlan id>
|
||||
* For example, the following will configure PF eth0 and the first VF on VLAN 10:
|
||||
*# ip link set dev eth0 vf 0 vlan 10
|
||||
*add a VLAN interface on the VF interface. For example:
|
||||
*# ip link add link eth2 name eth2.100 type vlan id 100
|
||||
* Note that the order in which you set the VF to promiscuous mode and add the
|
||||
*VLAN interface does not matter (you can do either first). The result in this
|
||||
*example is that the VF will get all traffic that is tagged with VLAN 100.
|
||||
*/
|
||||
int crete_set_vf_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos, __be16 vlan_proto)
|
||||
{
|
||||
int rc;
|
||||
struct crete_vf_info *vf;
|
||||
struct crete_priv *priv = netdev_priv(netdev);
|
||||
struct crete_core_dev *core_dev = priv->coredev;
|
||||
struct pci_dev *pdev = core_dev->pdev;
|
||||
struct crete_pf_info pf = core_dev->pf;
|
||||
u16 vlan_tag;
|
||||
|
||||
rc = crete_vf_ndo_prep(netdev, vf_id);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
vf = &pf.vf[vf_id];
|
||||
/* TODO: needed to implement proper handling of user priority,
|
||||
* currently fail the command if there is valid priority
|
||||
*/
|
||||
if (vlan_id > 4095 || qos)
|
||||
return -EINVAL;
|
||||
|
||||
vlan_tag = vlan_id;
|
||||
if (vlan_tag == vf->vlan)
|
||||
return 0;
|
||||
dev_err(&pdev->dev, "Set VF VLAN VF id %d VLAN:%d QOS:%d vlan_proto:%d\n",
|
||||
vf_id, vlan_id, qos, vlan_proto);
|
||||
//TBD, add adminQ cmd
|
||||
rc = crete_eswitch_set_vport_vlan(core_dev->eswitch,
|
||||
VPORT(vf_id), vlan_id, qos, htons(ETH_P_8021Q));
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev, "Set VF VLAN VF id %d VLAN:%d QOS:%d vlan_proto:%d failed, err:%d\n",
|
||||
vf_id, vlan_id, qos, vlan_proto, rc);
|
||||
return rc;
|
||||
}
|
||||
vf->vlan = vlan_tag;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*Virtual Function (VF) Tx Rate Limit
|
||||
*Use the ip command to configure the maximum or minimum Tx rate limit for a VF
|
||||
*from the PF interface.
|
||||
*For example, to set a maximum Tx rate limit of 8000Mbps for VF 0:
|
||||
*# ip link set eth0 vf 0 max_tx_rate 8000
|
||||
*For example, to set a minimum Tx rate limit of 1000Mbps for VF 0:
|
||||
*# ip link set eth0 vf 0 min_tx_rate 1000
|
||||
*1.If DCB or ADQ are enabled on a PF, you cannot set a minimum Tx rate on the
|
||||
*VFs associated with that PF.
|
||||
*2.If both DCB and ADQ are disabled on a PF, then you can set a minimum Tx rate
|
||||
*on the VFs associated with that PF.
|
||||
*3.If you set a minimum Tx rate limit on a PF for SR-IOV VFs and then apply a
|
||||
*DCB or ADQ configuration, the PF cannot guarantee the minimum Tx rate limits
|
||||
*for those VFs.
|
||||
*If you set a minimum Tx rate on VFs across multiple ports that have an
|
||||
*aggregate bandwidth over 100Gbps, the PFs cannot guarantee the minimum Tx rate
|
||||
*set for the VFs.
|
||||
*/
|
||||
int crete_set_vf_bw(struct net_device *netdev, int vf_id, int min_tx_rate, int max_tx_rate)
|
||||
{
|
||||
int rc;
|
||||
struct crete_vf_info *vf;
|
||||
struct crete_priv *priv = netdev_priv(netdev);
|
||||
struct crete_core_dev *core_dev = priv->coredev;
|
||||
struct pci_dev *pdev = core_dev->pdev;
|
||||
struct crete_pf_info pf = core_dev->pf;
|
||||
u32 pf_link_speed = 400000; /* TBD get from hw */
|
||||
|
||||
rc = crete_vf_ndo_prep(netdev, vf_id);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
vf = &pf.vf[vf_id];
|
||||
if (max_tx_rate > pf_link_speed) {
|
||||
dev_err(&pdev->dev, "max tx rate %d exceed PF link speed for VF %d\n",
|
||||
max_tx_rate, vf_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (min_tx_rate > pf_link_speed) {
|
||||
dev_err(&pdev->dev, "min tx rate %d is invalid for VF %d\n",
|
||||
min_tx_rate, vf_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (min_tx_rate == vf->min_tx_rate && max_tx_rate == vf->max_tx_rate)
|
||||
return 0;
|
||||
|
||||
rc = crete_eswitch_set_vport_rate(core_dev->eswitch,
|
||||
VPORT(vf_id), max_tx_rate, min_tx_rate);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev, "Set vf_bw failed %d, vf:%d max_rate min_rate:%d rc:%d\n",
|
||||
vf_id, max_tx_rate, min_tx_rate, rc);
|
||||
return rc;
|
||||
}
|
||||
vf->min_tx_rate = min_tx_rate;
|
||||
vf->max_tx_rate = max_tx_rate;
|
||||
dev_err(&pdev->dev, "Set VF %d vf_bw min_tx_rate:%d max_tx_rate:%d\n", vf_id,
|
||||
min_tx_rate, max_tx_rate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crete_set_vf_link_state(struct net_device *netdev, int vf_id, int link)
|
||||
{
|
||||
int rc;
|
||||
struct crete_vf_info *vf;
|
||||
struct crete_priv *priv = netdev_priv(netdev);
|
||||
struct crete_core_dev *core_dev = priv->coredev;
|
||||
struct pci_dev *pdev = core_dev->pdev;
|
||||
struct crete_pf_info pf = core_dev->pf;
|
||||
|
||||
rc = crete_vf_ndo_prep(netdev, vf_id);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
vf = &pf.vf[vf_id];
|
||||
|
||||
vf->flags &= ~(CRETE_VF_LINK_UP | CRETE_VF_LINK_FORCED);
|
||||
switch (link) {
|
||||
case IFLA_VF_LINK_STATE_AUTO:
|
||||
vf->flags |= CRETE_VF_LINK_UP;
|
||||
dev_err(&pdev->dev, "Set VF %d link_state Auto\n", vf_id);
|
||||
break;
|
||||
case IFLA_VF_LINK_STATE_DISABLE:
|
||||
vf->flags |= CRETE_VF_LINK_FORCED;
|
||||
dev_err(&pdev->dev, "Set VF %d link_state Disable\n", vf_id);
|
||||
break;
|
||||
case IFLA_VF_LINK_STATE_ENABLE:
|
||||
vf->flags |= CRETE_VF_LINK_UP | CRETE_VF_LINK_FORCED;
|
||||
dev_err(&pdev->dev, "Set VF %d link_state Enable\n", vf_id);
|
||||
break;
|
||||
default:
|
||||
dev_err(&pdev->dev, "Invalid link option\n");
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (vf->flags & (CRETE_VF_LINK_UP | CRETE_VF_LINK_FORCED)) {
|
||||
rc = crete_eswitch_set_vport_state(core_dev->eswitch, VPORT(vf_id), link);
|
||||
if (rc)
|
||||
dev_err(&pdev->dev, "Set link state failed %d, link:%d rc:%d\n",
|
||||
vf_id, link, rc);
|
||||
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
/*
|
||||
*MAC and VLAN Anti-Spoofing Feature for VFs
|
||||
*When a malicious driver on a Virtual Function (VF) interface attempts to send a
|
||||
*spoofed packet, it is dropped by the hardware and not transmitted.
|
||||
*NOTE: This feature can be disabled for a specific VF:
|
||||
*# ip link set <ethX> vf <vf id> spoofchk {off|on}
|
||||
*/
|
||||
int crete_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool setting)
|
||||
{
|
||||
int rc;
|
||||
struct crete_vf_info *vf;
|
||||
struct crete_priv *priv = netdev_priv(netdev);
|
||||
struct crete_core_dev *core_dev = priv->coredev;
|
||||
struct pci_dev *pdev = core_dev->pdev;
|
||||
struct crete_pf_info pf = core_dev->pf;
|
||||
bool old_setting = false;
|
||||
|
||||
rc = crete_vf_ndo_prep(netdev, vf_id);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
vf = &pf.vf[vf_id];
|
||||
|
||||
if (vf->flags & CRETE_VF_SPOOFCHK)
|
||||
old_setting = true;
|
||||
if (old_setting == setting)
|
||||
return 0;
|
||||
rc = crete_eswitch_set_vport_spoofchk(core_dev->eswitch, VPORT(vf_id), setting);
|
||||
if (rc)
|
||||
dev_err(&pdev->dev, "Set VF %d spoofchk %s rc:%d\n",
|
||||
vf_id, setting ? "ON":"OFF", rc);
|
||||
|
||||
dev_err(&pdev->dev, "Set VF %d spoofchk %s\n", vf_id, setting ? "ON":"OFF");
|
||||
|
||||
if (setting)
|
||||
vf->flags |= CRETE_VF_SPOOFCHK;
|
||||
else
|
||||
vf->flags &= ~CRETE_VF_SPOOFCHK;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*Trusted VFs and VF Promiscuous Mode
|
||||
*This feature allows you to designate a particular VF as trusted and allows that
|
||||
*trusted VF to request selective promiscuous mode on the Physical Function (PF).
|
||||
*To set a VF as trusted or untrusted, enter the following command in the
|
||||
*Hypervisor:
|
||||
*# ip link set dev <ethX> vf 1 trust [on|off]
|
||||
*NOTE: It's important to set the VF to trusted before setting promiscuous mode.
|
||||
*If the VM is not trusted, the PF will ignore promiscuous mode requests from the
|
||||
*VF. If the VM becomes trusted after the VF driver is loaded, you must make a
|
||||
*new request to set the VF to promiscuous.
|
||||
*Once the VF is designated as trusted, use the following commands in the VM to
|
||||
*set the VF to promiscuous mode. For promiscuous all:
|
||||
*# ip link set <ethX> promisc on
|
||||
* Where <ethX> is a VF interface in the VM
|
||||
*For promiscuous Multicast:
|
||||
*# ip link set <ethX> allmulticast on
|
||||
* Where <ethX> is a VF interface in the VM
|
||||
*/
|
||||
int crete_set_vf_trust(struct net_device *netdev, int vf_id, bool trusted)
|
||||
{
|
||||
int rc;
|
||||
struct crete_vf_info *vf;
|
||||
struct crete_priv *priv = netdev_priv(netdev);
|
||||
struct crete_core_dev *core_dev = priv->coredev;
|
||||
struct pci_dev *pdev = core_dev->pdev;
|
||||
struct crete_pf_info pf = core_dev->pf;
|
||||
|
||||
rc = crete_vf_ndo_prep(netdev, vf_id);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
vf = &pf.vf[vf_id];
|
||||
|
||||
dev_err(&pdev->dev, "Set VF %d trust %s\n", vf_id, trusted ? "ON":"OFF");
|
||||
rc = crete_eswitch_set_vport_trust(core_dev->eswitch, VPORT(vf_id), trusted);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev, "Set VF %d trust %s rc:%d\n", vf_id, trusted ? "ON":"OFF", rc);
|
||||
return rc;
|
||||
}
|
||||
if (trusted)
|
||||
vf->flags |= CRETE_VF_TRUST;
|
||||
else
|
||||
vf->flags &= ~CRETE_VF_TRUST;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crete_approve_mac(struct crete_core_dev *core_dev, const u8 *mac)
|
||||
{
|
||||
int rc = 0;
|
||||
struct pci_dev *pdev = core_dev->pdev;
|
||||
|
||||
if (crete_core_is_pf(core_dev))
|
||||
return 0;
|
||||
|
||||
if (is_valid_ether_addr(core_dev->vf.mac_addr))
|
||||
rc = -EADDRNOTAVAIL;
|
||||
/* admin Q to PF approve VF MAC */
|
||||
|
||||
dev_err(&pdev->dev, "VF MAC address %pM approved by the PF\n", mac);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -0,0 +1,88 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __CRETE_SRIOV_H
|
||||
#define __CRETE_SRIOV_H
|
||||
|
||||
struct crete_vf_context {
|
||||
int enabled;
|
||||
u64 port_guid;
|
||||
u64 node_guid;
|
||||
/* Valid bits are used to validate administrative guid only.
|
||||
* Enabled after ndo_set_vf_guid
|
||||
*/
|
||||
u8 port_guid_valid:1;
|
||||
u8 node_guid_valid:1;
|
||||
};
|
||||
|
||||
#define CRETE_VF_QOS 0x1
|
||||
#define CRETE_VF_SPOOFCHK 0x2
|
||||
#define CRETE_VF_LINK_FORCED 0x4
|
||||
#define CRETE_VF_LINK_UP 0x8
|
||||
#define CRETE_VF_TRUST 0x10
|
||||
|
||||
/*stub micro define */
|
||||
#define FUNC_QCFG_RESP_FLAGS_TRUSTED_VF 0x40UL
|
||||
|
||||
|
||||
|
||||
struct crete_vf_info {
|
||||
u16 fw_fid;
|
||||
u8 mac_addr[ETH_ALEN]; /* PF assigned MAC Address */
|
||||
u8 vf_mac_addr[ETH_ALEN]; /* VF assigned MAC address, only stored by PF. */
|
||||
u16 vlan;
|
||||
u16 func_qcfg_flags;
|
||||
u32 flags;
|
||||
u32 min_tx_rate;
|
||||
u32 max_tx_rate;
|
||||
u32 enabled;
|
||||
void *hwrm_cmd_req_addr;
|
||||
dma_addr_t hwrm_cmd_req_dma_addr;
|
||||
};
|
||||
int crete_get_func_caps(struct crete_core_dev *core_dev);
|
||||
int crete_sriov_init(struct crete_core_dev *core_dev);
|
||||
void crete_sriov_cleanup(struct crete_core_dev *dev);
|
||||
int crete_pci_sriov_configure(struct pci_dev *dev, int num_vfs);
|
||||
int crete_get_vf_config(struct net_device *netdev, int vf_id, struct ifla_vf_info *ivi);
|
||||
int crete_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac);
|
||||
int crete_set_vf_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos, __be16 vlan_proto);
|
||||
int crete_set_vf_bw(struct net_device *netdev, int vf_id, int min_tx_rate, int max_tx_rate);
|
||||
int crete_set_vf_link_state(struct net_device *netdev, int vf_id, int link);
|
||||
int crete_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool setting);
|
||||
int crete_set_vf_trust(struct net_device *netdev, int vf_id, bool trust);
|
||||
int crete_approve_mac(struct crete_core_dev *core_dev, const u8 *mac);
|
||||
bool crete_is_trusted_vf(struct net_device *netdev, struct crete_vf_info *vf);
|
||||
void crete_device_disable_sriov(struct crete_core_dev *core_dev, int num_vfs, bool clear_vf);
|
||||
|
||||
#endif /* __CRETE_SRIOV_H */
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,126 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __CRETE_SRIOV_SYSFS_H
|
||||
#define __CRETE_SRIOV_SYSFS_H
|
||||
|
||||
enum {
|
||||
CRETE_RATE_LIMIT_RX,
|
||||
CRETE_RATE_LIMIT_TX,
|
||||
};
|
||||
|
||||
enum crete_flow_meter_mode {
|
||||
CRETE_RATE_LIMIT_BPS,
|
||||
CRETE_RATE_LIMIT_PPS,
|
||||
};
|
||||
|
||||
enum {
|
||||
CRETE_RATE_LIMIT_DATA_RATE,
|
||||
CRETE_RATE_LIMIT_DATA_BURST,
|
||||
CRETE_RATE_LIMIT_DATA_PACKETS_DROPPED,
|
||||
CRETE_RATE_LIMIT_DATA_BYTES_DROPPED,
|
||||
};
|
||||
|
||||
#define CRETE_ESW_QOS_SYSFS_GROUP_MAX_ID 255
|
||||
#define CRETE_ESW_QOS_NON_SYSFS_GROUP (CRETE_ESW_QOS_SYSFS_GROUP_MAX_ID + 1)
|
||||
|
||||
struct crete_sriov_vf_meter_type {
|
||||
int rx_tx;
|
||||
int xps;
|
||||
};
|
||||
|
||||
|
||||
struct crete_sriov_vf_sysfs {
|
||||
struct crete_core_dev *dev;
|
||||
struct kobject kobj;
|
||||
struct kobject page_kobj;
|
||||
int vf;
|
||||
union {
|
||||
struct crete_sriov_vf_meters *meters;
|
||||
struct crete_sriov_vf_meter_type meter_type;
|
||||
};
|
||||
};
|
||||
|
||||
struct crete_sriov_vf_meters {
|
||||
struct kobject *kobj;
|
||||
struct kobject *rx_kobj;
|
||||
struct kobject *tx_kobj;
|
||||
struct crete_sriov_vf_sysfs meters[4];
|
||||
};
|
||||
|
||||
struct mlxdevm_rate_group {
|
||||
struct list_head list;
|
||||
char *name;
|
||||
u64 tx_max;
|
||||
u64 tx_share;
|
||||
};
|
||||
|
||||
|
||||
struct crete_esw_rate_group {
|
||||
struct crete_core_dev *dev;
|
||||
struct mlxdevm_rate_group devm;
|
||||
u32 tsar_ix;
|
||||
u32 max_rate;
|
||||
u32 min_rate;
|
||||
u32 bw_share;
|
||||
struct list_head list;
|
||||
|
||||
/* sysfs group related fields */
|
||||
struct kobject kobj;
|
||||
u32 group_id;
|
||||
u32 num_vports;
|
||||
};
|
||||
|
||||
|
||||
enum port_state_policy {
|
||||
CRETE_POLICY_DOWN = 0,
|
||||
CRETE_POLICY_UP = 1,
|
||||
CRETE_POLICY_FOLLOW = 2,
|
||||
CRETE_POLICY_INVALID = 0xffffffff
|
||||
};
|
||||
|
||||
int crete_create_vfs_sysfs(struct crete_core_dev *dev, int num_vfs);
|
||||
void crete_destroy_vfs_sysfs(struct crete_core_dev *dev, int num_vfs);
|
||||
|
||||
int crete_create_vf_group_sysfs(struct crete_core_dev *dev,
|
||||
u32 group_id, struct kobject *group_kobj);
|
||||
void crete_destroy_vf_group_sysfs(struct crete_core_dev *dev,
|
||||
struct kobject *group_kobj);
|
||||
|
||||
int crete_sriov_sysfs_init(struct crete_core_dev *dev);
|
||||
void crete_sriov_sysfs_cleanup(struct crete_core_dev *dev);
|
||||
|
||||
|
||||
#endif /* __CRETE_SRIOV_SYSFS_H */
|
||||
|
@ -0,0 +1,37 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#include "crete.h"
|
||||
#include "crete_stub.h"
|
||||
|
||||
|
||||
|
@ -0,0 +1,49 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#ifndef __CRETE_STUB_H
|
||||
#define __CRETE_STUB_H
|
||||
#include <linux/netdevice.h>
|
||||
#include "crete.h"
|
||||
/*tmp micro*/
|
||||
#define PCI_VENDOR_ID_CRETE 0x1f53
|
||||
#define PF_DEVICE_ID 0x1B20
|
||||
#define VF_DEVICE_ID 0x1B21
|
||||
#define PF_DEVICE_ID_SIM 0x9527
|
||||
#define VF_DEVICE_ID_SIM 0x9523
|
||||
#define PF_DEVICE_ID_NIC 0x3B20
|
||||
#define VF_DEVICE_ID_NIC 0x3B21
|
||||
#define PF_DEVICE_ID_CMCC 0x2C20
|
||||
#define VF_DEVICE_ID_CMCC 0x2C22
|
||||
#define PF_DEVICE_ID_FAKE 0x1C00
|
||||
|
||||
#endif /* __CRETE_STUB_H */
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,636 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* crete_ring.c
|
||||
*
|
||||
* Jmnd crete driver
|
||||
*
|
||||
* Authors: Jmnd
|
||||
*
|
||||
*/
|
||||
#ifndef __CRETE_IOQUEUE_H
|
||||
#define __CRETE_IOQUEUE_H
|
||||
|
||||
#define CRETE_RING_DEFAULT_DEEP 1024UL
|
||||
#define CRETE_ENTRY_DFAULT_SIZE 16UL
|
||||
#define CRETE_PKTTYPE0_LENGTH 1UL
|
||||
#define CRETE_PKTTYPE1_LENGTH 2UL
|
||||
#define CRETE_PKTTYPE2_LENGTH 3UL
|
||||
#define CRETE_PKTTYPE3_LENGTH 4UL
|
||||
|
||||
enum {
|
||||
BD_SIZE16 = 0,
|
||||
BD_SIZE32,
|
||||
BD_SIZE48,
|
||||
BD_SIZE64
|
||||
};
|
||||
|
||||
enum {
|
||||
TUNNEL_NONE = 0x0,
|
||||
TUNNEL_ONE = 0x2,
|
||||
TUNNEL_TWO = 0x3,
|
||||
TUNNEL_ERR = 0x1
|
||||
};
|
||||
|
||||
#define CRETE_PKT_LENGTH(bd_size) \
|
||||
(bd_size == BD_SIZE16 ? CRETE_PKTTYPE0_LENGTH : \
|
||||
(bd_size == BD_SIZE32 ? CRETE_PKTTYPE1_LENGTH : \
|
||||
(bd_size == BD_SIZE48 ? CRETE_PKTTYPE2_LENGTH : \
|
||||
(bd_size == BD_SIZE64 ? CRETE_PKTTYPE3_LENGTH : 0))))
|
||||
|
||||
#define CRETE_RX_OFFSET (NET_SKB_PAD + NET_IP_ALIGN)
|
||||
#define CRETE_RX_DMA_OFFSET NET_SKB_PAD
|
||||
|
||||
#define CRETE_TX_DIR 0
|
||||
#define CRETE_RX_DIR 1
|
||||
#define CRETE_TX_DIR_BITS (1 << 4)
|
||||
#define CRETE_RX_DIR_BITS (1 << 3)
|
||||
|
||||
|
||||
/* The feature bitmap for Crete netdev */
|
||||
#define CRETE_NET_F_SOP_PADDING 0
|
||||
#define CRETE_NET_F_EOP_PADDING 1
|
||||
#define CRETE_NET_F_AUTO_INTR_SUP 2
|
||||
#define CRETE_NET_F_INTR_MOD 3
|
||||
#define CRETE_NET_F_TX_INORDER 5
|
||||
#define CRETE_NET_F_CQE_AGG 7
|
||||
#define CRETE_NET_F_RX_MERGE 8
|
||||
|
||||
/* The feature bitmap for Crete offload */
|
||||
#define CRETE_NET_F_RX_VLAN_FILTER 0
|
||||
#define CRETE_NET_F_RX_VLAN_STRIP 1
|
||||
#define CRETE_NET_F_RX_IPV4_CSUM 2
|
||||
#define CRETE_NET_F_RX_UDP_CSUM 3
|
||||
#define CRETE_NET_F_RX_TCP_CSUM 4
|
||||
#define CRETE_NET_F_RX_SCTP_CSUM 5
|
||||
#define CRETE_NET_F_RX_TCP_LRO 6
|
||||
#define CRETE_NET_F_RX_RSS_HASH 7
|
||||
#define CRETE_NET_F_RX_TIMESTAMP 8
|
||||
#define CRETE_NET_F_RX_METADATA 9
|
||||
|
||||
#define CRETE_NET_F_TX_IPV4_CSUM 32
|
||||
#define CRETE_NET_F_TX_TCP_CSUM 33
|
||||
#define CRETE_NET_F_TX_UDP_CSUM 34
|
||||
#define CRETE_NET_F_TX_SCTP_CSUM 35
|
||||
#define CRETE_NET_F_TX_OUTER_IPV4_CSUM 36
|
||||
#define CRETE_NET_F_TX_OUTER_UDP_CSUM 37
|
||||
#define CRETE_NET_F_TX_TCP_TSO 38
|
||||
#define CRETE_NET_F_TX_IP_TNL_TSO 39
|
||||
#define CRETE_NET_F_TX_UDP_TNL_TSO 40
|
||||
#define CRETE_NET_F_TX_VLAN_INSERT 41
|
||||
#define CRETE_NET_F_TX_QINQ_INSERT 42
|
||||
#define CRETE_NET_F_TX_SEND_ON_TIMESTAMP 43
|
||||
#define CRETE_NET_F_TX_METADATA 44
|
||||
|
||||
#define CRETE_NET_F_VPORT_RX_FLOW_TABLE 59
|
||||
#define CRETE_NET_F_FDB_TABLE 60
|
||||
#define CRETE_NET_F_FLOW_REDIR_TABLE 61
|
||||
#define CRETE_NET_F_L2_SWITCH_TABLE 62
|
||||
#define CRETE_NET_F_VSWITCH_OFFLOAD 63
|
||||
|
||||
enum CRETE_DB_TYPE {
|
||||
DB_RXRQ = 0,
|
||||
DB_TXSQ,
|
||||
DB_RXCQ_ARM,
|
||||
DB_TXCQ_ARM
|
||||
};
|
||||
|
||||
#define CRETE_RING_MEM_SIZE 4
|
||||
#define CRETE_TX_FREE_SIZE_THD 16
|
||||
#define CRETE_TX_CPR_SIZE_PTH 8
|
||||
|
||||
#define CRETE_SETBDSIZE(x, size) (x->bd_size = size)
|
||||
|
||||
#define CRETE_NEXTID(x, val, mask) \
|
||||
((x + val) & mask)
|
||||
|
||||
#define CRETE_DESC_VALID(txcmp, txcpr) \
|
||||
(txcmp->wrap_counter == (1 ^ txcpr->wrap_counter))
|
||||
|
||||
#define CRETE_DESC_BUFID(txcmp) \
|
||||
(txcmp->buf_id)
|
||||
|
||||
#define CRETE_DESC_TYPE(txcmp) \
|
||||
(txcmp->bd_type)
|
||||
|
||||
#define CRETE_DESC_SIZE(txcmp) \
|
||||
(txcmp->bd_size)
|
||||
|
||||
#define CRETE_DESC_BDLEN(txbd) \
|
||||
(CRETE_PKT_LENGTH(CRETE_DESC_SIZE(txbd)))
|
||||
|
||||
#define CRETE_RX_PKT_LEN(bd) \
|
||||
(le16_to_cpu(bd->pkt_len))
|
||||
|
||||
#define CRETE_WRITE_64BITADDR(s, le64_val) \
|
||||
do { \
|
||||
s->addr_lo = le64_val & 0xFFFFFFFF; \
|
||||
s->addr_hi = (le64_val >> 32UL) & 0xFFFFFFFF; \
|
||||
}while(0)
|
||||
|
||||
#define crete_err(__dev, format, ...) \
|
||||
dev_err(__dev, "%s:%d:(pid %d): " format, \
|
||||
__func__, __LINE__, current->pid, \
|
||||
##__VA_ARGS__)
|
||||
|
||||
#define crete_info(__dev, format, ...) \
|
||||
dev_info(__dev, "%s:%d:(pid %d): " format, \
|
||||
__func__, __LINE__, current->pid, \
|
||||
##__VA_ARGS__)
|
||||
|
||||
#define crete_warn(__dev, format, ...) \
|
||||
dev_warn(__dev, "%s:%d:(pid %d): " format, \
|
||||
__func__, __LINE__, current->pid, \
|
||||
##__VA_ARGS__)
|
||||
|
||||
/****begin define the io queue struct ****/
|
||||
|
||||
/**
|
||||
* struct crete_rx_bd - crete rx rqe define
|
||||
* @pkttype: pkttype 0 0:16bytes 1:2*16bytes 2:3*16bytes 3:4*16bytes
|
||||
* @buf_id: the packet buffer id ,do not need to convert order sequence.
|
||||
* @resv: resver bytes
|
||||
* @buf_len: buffer length
|
||||
* @addr_lo: address lower32
|
||||
* @addr_hi: address high32
|
||||
*/
|
||||
struct crete_rx_bd {
|
||||
u16 bd_size:3;
|
||||
u16 rsv0:13;
|
||||
u16 buf_id;
|
||||
__le16 buf_len;
|
||||
__le16 resv;
|
||||
__le32 addr_lo;
|
||||
__le32 addr_hi;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct crete_rxcq_32bd - crete rx rqe define
|
||||
* @pkttype: pkttype 0 0:16bytes 1:2*16bytes 2:3*16bytes 3:4*16bytes
|
||||
* @vlan_strip: the packet buffer id
|
||||
* @rss_validate: resver bytes
|
||||
* @outer_vlan_tpid: buffer length
|
||||
* @addr_lo: address lower32
|
||||
* @addr_hi: address high32
|
||||
* Little Endian Only
|
||||
*/
|
||||
struct crete_rxcq_32bd_low {
|
||||
/* dw0 */
|
||||
u16 bd_size:3;
|
||||
u16 bd_type:2;
|
||||
u16 rsv0:2;
|
||||
u16 wrap_counter:1;
|
||||
u16 pkt_err_type:3;
|
||||
u16 l4_cksum_ok:1;
|
||||
u16 l3_cksum_ok:1;
|
||||
u16 l2_type:2;
|
||||
u16 ptp_pkt:1;
|
||||
u16 buf_id;
|
||||
|
||||
/* dw1 */
|
||||
u32 pkt_len:17;
|
||||
u32 l4_hdr_type:3;
|
||||
u32 l3_hdr_type:3;
|
||||
u32 outer_l3_type:1;
|
||||
u32 ip_frag:1;
|
||||
u32 tunnel_mode:2;
|
||||
u32 l2_valid:1;
|
||||
u32 outer_ip_ext_opts:1;
|
||||
u32 tunnel_ip_ext_opts:1;
|
||||
u32 tunnel_l3_type:1;
|
||||
u32 ip_ext_opts:1;
|
||||
|
||||
/* dw2 */
|
||||
u16 src_port_id:12;
|
||||
u16 rsv1:4;
|
||||
u16 pkt_type:4;
|
||||
u16 rsv2:2;
|
||||
u16 rss_level:2;
|
||||
u16 rss_type:8;
|
||||
|
||||
/* dw3 */
|
||||
__le32 rss_hash;
|
||||
|
||||
/* dw4 */
|
||||
__le32 timestamp;
|
||||
|
||||
/* dw5 */
|
||||
__le16 vlan_tci;
|
||||
u16 strip_vlan_tpid:3;
|
||||
u16 vlan_strip:1;
|
||||
u16 rsv3:4;
|
||||
u16 rx_drop_counter:8;
|
||||
|
||||
/* dw6 */
|
||||
__le32 metadata0;
|
||||
|
||||
/* dw7 */
|
||||
__le32 metadata1;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct crete_rxcq_32bd_hi - crete rx rqe define
|
||||
* @rsv0:
|
||||
* @wrap_counter:
|
||||
* @rsv1: resver bytes
|
||||
* @flow_tag0: buffer length
|
||||
* @timestamps: address lower32
|
||||
* @addr_hi: address high32
|
||||
*/
|
||||
struct crete_rxcq_32bd_hi {
|
||||
/* dw 0 */
|
||||
u16 rsv0:7;
|
||||
u16 wrap_counter:1;
|
||||
u16 lro_seg_num:8;
|
||||
__le16 lro_checksum;
|
||||
|
||||
/* dw 1 */
|
||||
u16 rsv1:4;
|
||||
u16 lro_tcp_psh:1;
|
||||
u16 lro_abrt:3;
|
||||
u16 lro_min_ttl:8;
|
||||
__le16 lro_tcp_win;
|
||||
|
||||
/* dw 2 */
|
||||
__le32 lro_ack_seq_num;
|
||||
|
||||
/* dw 3 */
|
||||
u32 timestamp_type:2;
|
||||
u32 rsv2:30;
|
||||
|
||||
/* dw 4 */
|
||||
__le32 timestamp_low;
|
||||
|
||||
/* dw 5 */
|
||||
__le32 timestamp_high;
|
||||
|
||||
/* dw 6 */
|
||||
__le32 metadata2;
|
||||
|
||||
/* dw 7 */
|
||||
__le32 metadata3;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct crete_rxcq_64bd - rx 64bytes bd
|
||||
* @bd_l: low 32 bytes bd
|
||||
* @bd_h: high 32 bytes bd
|
||||
*/
|
||||
struct crete_rxcq_64bd {
|
||||
struct crete_rxcq_32bd_low bd_l;
|
||||
struct crete_rxcq_32bd_hi bd_h;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct crete_txbd - 16bytes no offloads
|
||||
* @pkt_type:
|
||||
* @no_complete:
|
||||
*/
|
||||
struct crete_txbd {
|
||||
/* dw 0 */
|
||||
u16 bd_size:3;
|
||||
u16 rsv:2;
|
||||
u16 eop:1;
|
||||
u16 debug_trace:1;
|
||||
u16 rsv0:1;
|
||||
u16 bd_num:6;
|
||||
u16 outmost_l3_cksum:1;
|
||||
u16 outmost_l4_cksum:1;
|
||||
u16 buf_id;
|
||||
|
||||
/* dw 1 */
|
||||
u16 dst_port:12;
|
||||
u16 rsv1:3;
|
||||
u16 dst_port_valid:1;
|
||||
__le16 buf_len;
|
||||
|
||||
/* dw 2 */
|
||||
__le32 addr_lo;
|
||||
|
||||
/* dw 3 */
|
||||
__le32 addr_hi;
|
||||
} __packed;
|
||||
|
||||
struct crete_txbd_l1 {
|
||||
/* dw 0 */
|
||||
__le16 vlan_cli;
|
||||
u16 vlan_insert:1;
|
||||
u16 vlan_tpid:3;
|
||||
u16 out3rd_l3_cksum:1;
|
||||
u16 out3rd_l4_cksum:1;
|
||||
u16 out2nd_l3_cksum:1;
|
||||
u16 out2nd_l4_cksum:1;
|
||||
u16 mac_timestamp_en:1;
|
||||
u16 udp_tunnel_sport:1;
|
||||
u16 rsv0:6;
|
||||
|
||||
/* dw 1 */
|
||||
u8 outer_l4_offset;
|
||||
u8 outer_l3_offset;
|
||||
u8 l4_offset;
|
||||
u8 l3_offset;
|
||||
|
||||
/* dw 2 */
|
||||
u16 rsv1:15;
|
||||
u16 tso_en:1;
|
||||
u16 l4_tunnel_type:2;
|
||||
u16 mss:14;
|
||||
|
||||
/* dw 3 */
|
||||
__le32 metadata;
|
||||
} __packed;
|
||||
|
||||
struct crete_32txbd {
|
||||
struct crete_txbd bd_l0;
|
||||
struct crete_txbd_l1 bd_l1;
|
||||
} __packed;
|
||||
|
||||
struct crete_txbd_l2 {
|
||||
/* dw 0 */
|
||||
u16 rsv0:15;
|
||||
u16 meter_valid:1;
|
||||
__le16 meter_len;
|
||||
|
||||
/* dw 1 */
|
||||
__le16 meterid0;
|
||||
__le16 meterid1;
|
||||
|
||||
/* dw 2 */
|
||||
__le16 meterid2;
|
||||
__le16 meterid3;
|
||||
|
||||
/* dw 3 */
|
||||
__le16 meterid4;
|
||||
__le16 meterid5;
|
||||
|
||||
} __packed;
|
||||
|
||||
struct crete_48txbd {
|
||||
struct crete_txbd bd_l0;
|
||||
struct crete_txbd_l1 bd_l1;
|
||||
struct crete_txbd_l2 bd_l2;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct tx_cq_bd
|
||||
* @pkt_type:
|
||||
* @rsv0:
|
||||
* @timestamp_high_flag:
|
||||
*/
|
||||
struct tx_cq_bd {
|
||||
/* dw 0 */
|
||||
u16 bd_size:3;
|
||||
u16 bd_type:2;
|
||||
u16 rsv0:2;
|
||||
u16 wrap_counter:1;
|
||||
u16 rsv1:8;
|
||||
__le16 buf_id;
|
||||
|
||||
/* dw 1 */
|
||||
__le32 errors;
|
||||
|
||||
/* dw 2 */
|
||||
__le32 rsv2;
|
||||
|
||||
/* dw 3 */
|
||||
__le32 timestamps;
|
||||
} __packed;
|
||||
|
||||
union crete_db_info {
|
||||
__le32 val;
|
||||
struct {
|
||||
__le16 index;
|
||||
u16 vqn:11;
|
||||
u16 debug_trace:1;
|
||||
u16 type:4;
|
||||
} db_info;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct crete_db - crete rx db define
|
||||
* @val: doorbell register value, notice le mode
|
||||
* @type: sq / rq / eq
|
||||
* @vqn: qp index
|
||||
* @index: sq/rq entry bd index
|
||||
*/
|
||||
struct crete_db {
|
||||
void __iomem *db_addr;
|
||||
spinlock_t lock;
|
||||
union {
|
||||
__le32 val;
|
||||
struct {
|
||||
u32 type:5;
|
||||
u32 resv:3;
|
||||
u32 vqn:8;
|
||||
__le16 index:16;
|
||||
} db_info;
|
||||
};
|
||||
};
|
||||
|
||||
/****end define the io queue struct ****/
|
||||
|
||||
/**
|
||||
* struct crete_rx_buf
|
||||
* @page page
|
||||
* @data:point to the rxbuf cpu address
|
||||
* @mapping:device dma handle address
|
||||
* kref: used for the
|
||||
*/
|
||||
struct crete_rx_buf {
|
||||
refcount_t kref;
|
||||
struct page *page;
|
||||
void *data;
|
||||
u8 *data_ptr;
|
||||
dma_addr_t mapping;
|
||||
// struct kref kref;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct crete_tx_buf
|
||||
* @skb: skb buffer address
|
||||
* @mapping:device dma handle address
|
||||
* @kref: ref counter
|
||||
* @rx_prod: cons the rx production index
|
||||
*/
|
||||
struct crete_tx_buf {
|
||||
// struct kref kref;
|
||||
refcount_t kref;
|
||||
struct sk_buff *skb;
|
||||
dma_addr_t mapping;
|
||||
void (*release)(struct kref *kref);
|
||||
u16 rx_prod;
|
||||
u16 nr_frags;
|
||||
u16 nr_bdnum;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct crete_rxring_mem
|
||||
* all the qp memory info need the struct
|
||||
* fly with bp memory
|
||||
* @rx_bd: rx sq virtual memory address
|
||||
* @rx_bd_map: rx bd dma handle
|
||||
*/
|
||||
struct crete_ring_mem {
|
||||
void *ring_base[CRETE_RING_MEM_SIZE];
|
||||
dma_addr_t rx_bd_map[CRETE_RING_MEM_SIZE];
|
||||
};
|
||||
|
||||
struct crete_rxcp_ring_info {
|
||||
void *rxcq_base;
|
||||
void *priv; // used for crete_napi
|
||||
dma_addr_t rxcq_mapping;
|
||||
size_t bd_len;
|
||||
u16 cp_prod;
|
||||
u16 cp_cons;
|
||||
u32 ring_size;
|
||||
u32 ring_mask;
|
||||
u8 wrap_counter:1;
|
||||
};
|
||||
|
||||
struct crete_txcp_ring_info {
|
||||
void *txcq_base;
|
||||
void *priv; // used for crete_napi
|
||||
dma_addr_t txcq_mapping;
|
||||
size_t bd_len;
|
||||
u16 cp_prod;
|
||||
u16 cp_cons;
|
||||
u32 ring_size;
|
||||
u32 ring_mask;
|
||||
atomic_t ring_avail;
|
||||
u8 wrap_counter:1;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct crete_rxring
|
||||
* @rx_bd:rx ring descripion
|
||||
* @db:ring doorbell
|
||||
* @rx_buf: rxring buffer
|
||||
*/
|
||||
struct crete_rxring_info {
|
||||
struct crete_rx_bd *rx_bd;
|
||||
dma_addr_t rx_bd_mapping;
|
||||
size_t bd_len;
|
||||
struct crete_rx_buf *rx_buf;
|
||||
struct crete_rxcp_ring_info *cpring;
|
||||
void *priv; // used for crete_napi
|
||||
refcount_t jref;
|
||||
struct crete_db db;
|
||||
struct crete_rxq_stats *rxq_stats;
|
||||
u16 rx_dbprod;
|
||||
u16 rx_prod;
|
||||
u16 rx_cons;
|
||||
u16 rx_ring_size;
|
||||
u16 rx_ring_mask;
|
||||
u8 queue_id;
|
||||
u8 id;
|
||||
u16 vec;
|
||||
};
|
||||
|
||||
struct crete_txring_info {
|
||||
struct crete_txbd *tx_bd;
|
||||
dma_addr_t tx_bd_mapping;
|
||||
size_t bd_len;
|
||||
struct crete_db *db;
|
||||
struct crete_tx_buf *tx_buf;
|
||||
struct crete_txcp_ring_info *cpring;
|
||||
void *priv; // used for crete_napi
|
||||
//struct crete_db db;
|
||||
struct crete_txq_stats *txq_stats;
|
||||
u16 tx_prod;
|
||||
u16 tx_dbprod;
|
||||
u16 tx_cons;
|
||||
u16 tx_ring_size;
|
||||
u16 tx_ring_mask;
|
||||
refcount_t jref;
|
||||
u8 id;
|
||||
u16 vec;
|
||||
atomic_t ring_avail;
|
||||
u8 kick_pending:1;
|
||||
|
||||
};
|
||||
|
||||
struct crete_napi {
|
||||
struct napi_struct napi;
|
||||
struct crete_core_dev *cdev;
|
||||
|
||||
union {
|
||||
struct crete_rxring_info *rxring;
|
||||
struct crete_txring_info *txring;
|
||||
};
|
||||
|
||||
union {
|
||||
struct crete_rxcp_ring_info *rxcpring;
|
||||
struct crete_txcp_ring_info *txcpring;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
static inline u32 crete_tx_avail(struct crete_txring_info *txr)
|
||||
{
|
||||
barrier();
|
||||
// return txr->tx_ring_size - ((txr->tx_prod - txr->tx_cons) & txr->tx_ring_mask);
|
||||
return atomic_read(&txr->ring_avail);
|
||||
}
|
||||
|
||||
static inline u32 crete_tx_length(struct crete_txring_info *txr)
|
||||
{
|
||||
barrier();
|
||||
return (txr->tx_ring_size - atomic_read(&txr->ring_avail));
|
||||
}
|
||||
|
||||
extern struct crete_core_dev *g_cdev;
|
||||
//extern int crete_cdev_cap_init(struct crete_core_dev *cdev);
|
||||
extern netdev_tx_t crete_start_xmit(struct sk_buff *skb,
|
||||
struct net_device *dev);
|
||||
extern int crete_poll_tx(struct napi_struct *napi, int budget);
|
||||
extern int crete_poll_rx(struct napi_struct *napi, int budget);
|
||||
extern int crete_features_negotiate(struct crete_core_dev *cdev);
|
||||
extern int crete_close(struct net_device *dev);
|
||||
extern int crete_open(struct net_device *dev);
|
||||
|
||||
/*
|
||||
* static inline void crete_txbuf_release(struct kref *kref, struct device *dev)
|
||||
* {
|
||||
* struct crete_tx_buf *txbuf;
|
||||
* struct
|
||||
* txbuf = container_of(kref, struct crete_tx_buf, kref);
|
||||
* if (!txbuf)
|
||||
* return;
|
||||
* dma_unmap_single(&pdev->dev, dma_unmap_addr(tx_buf, mapping),
|
||||
* skb_headlen(skb), DMA_TO_DEVICE);
|
||||
* dev_kfree_skb_any(skb);
|
||||
* }
|
||||
*/
|
||||
|
||||
#endif /* __CRETE_IOQUEUE_H */
|
@ -0,0 +1,96 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2023, Jaguar Micro. All rights reserved */
|
||||
|
||||
#ifndef _KCOMPAT_STD_DEFS_H_
|
||||
#define _KCOMPAT_STD_DEFS_H_
|
||||
|
||||
/* This file contains the definitions for what kernel features need backports
|
||||
* for a given kernel. It targets only the standard stable kernel releases.
|
||||
* It must check only LINUX_VERSION_CODE and assume the kernel is a standard
|
||||
* release, and not a custom distribution.
|
||||
*
|
||||
* It must define HAVE_<FLAG> and NEED_<FLAG> for features. It must not
|
||||
* implement any backports, instead leaving the implementation to the
|
||||
* kcompat_impl.h header.
|
||||
*
|
||||
* If a feature can be easily implemented as a replacement macro or fully
|
||||
* backported, use a NEED_<FLAG> to indicate that the feature needs
|
||||
* a backport. (If NEED_<FLAG> is undefined, then no backport for that feature
|
||||
* is needed).
|
||||
*
|
||||
* If a feature cannot be easily implemented in kcompat directly, but
|
||||
* requires drivers to make specific changes such as stripping out an entire
|
||||
* feature or modifying a function pointer prototype, use a HAVE_<FLAG>.
|
||||
*/
|
||||
|
||||
#ifndef LINUX_VERSION_CODE
|
||||
#error "LINUX_VERSION_CODE is undefined"
|
||||
#endif
|
||||
|
||||
#ifndef KERNEL_VERSION
|
||||
#error "KERNEL_VERSION is undefined"
|
||||
#endif
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 18, 0))
|
||||
#define CONFIG_DEVLINK_WITHOUT_FLASH
|
||||
#define CONFIG_WITHOUT_DEVLINK_PARAM_ETH
|
||||
// #define NEED_ETH_HW_ADDR_SET
|
||||
#endif /* 4,18,0 */
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))
|
||||
#define NEED_ETH_HW_ADDR_SET
|
||||
#endif /* 5.10.0 */
|
||||
|
||||
|
||||
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(5, 10, 134))
|
||||
#define NEED_ETH_HW_ADDR_SET
|
||||
#define CONFIG_WITHOUT_DEVLINK_PARAM_ETH
|
||||
#define HAVE_DEVLINK_REGISTER_SETS_DEV
|
||||
#define NEED_DEVLINK_ALLOC_SETS_DEV
|
||||
#endif /* 5.10.134 */
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0))
|
||||
#define CONFIG_DEVLINK_CARRYOUT_OPTIMIZE
|
||||
#endif /* 5.11.0 */
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0))
|
||||
#define CONFIG_ETHTOOL_EXTEND_RINGPARAM
|
||||
#endif /* 5.17.0 */
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0))
|
||||
#define NETIF_NAPI_ADD_NEWAPI
|
||||
#endif /* 5.19.0 */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0))
|
||||
#else /* >=6.1.0 */
|
||||
#define CONFIG_WITHOUT_DEVLINK_PARAM_ETH
|
||||
#endif /* 6.1.0 */
|
||||
|
||||
/*
|
||||
* about the anolis 5.10.134-14 kernel version
|
||||
* auxliary define with return int value
|
||||
*/
|
||||
#ifdef SNIC_ANOLIS_VERSION14
|
||||
// #define NEED_ETH_HW_ADDR_SET
|
||||
#define CONFIG_WITHOUT_DEVLINK_PARAM_ETH
|
||||
#define HAVE_DEVLINK_REGISTER_SETS_DEV
|
||||
#define NEED_DEVLINK_ALLOC_SETS_DEV
|
||||
#endif
|
||||
|
||||
#ifdef BCLINUX2110U4
|
||||
#undef NEED_ETH_HW_ADDR_SET
|
||||
#define CONFIG_ETHTOOL_EXTEND_RINGPARAM
|
||||
#endif
|
||||
|
||||
#ifdef SNIC_OPENEULER_VERSION136
|
||||
#define CONFIG_ETHTOOL_EXTEND_RINGPARAM
|
||||
#endif
|
||||
|
||||
#endif /* _KCOMPAT_STD_DEFS_H_ */
|
@ -0,0 +1,108 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguarmicro Technologies, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef JM_RDMA_H
|
||||
#define JM_RDMA_H
|
||||
#include <linux/io.h>
|
||||
#ifndef USE_JM_AUX_BUS
|
||||
#include <linux/auxiliary_bus.h>
|
||||
#else
|
||||
#include "linux/auxiliary_bus.h"
|
||||
#endif
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
struct jm_rdma_core;
|
||||
struct jm_rdma_adev;
|
||||
|
||||
/*
|
||||
* struct device *(*get_device)(struct jm_rdma_core *rdma);
|
||||
* Get struct device related with this auxiliary_device.
|
||||
* For example:
|
||||
* return &pci_dev.dev;
|
||||
*
|
||||
* void (*get_dev_info)(struct jm_rdma_core *rdma, u8 *feature,
|
||||
* u8 *rev_id, u16 *dev_id);
|
||||
* Get device's information.
|
||||
* For example:
|
||||
* *rev_id = pci_dev.revision;
|
||||
* *dev_id = pci_dev.device;
|
||||
* *vendor = pci_dev.vendor;
|
||||
*
|
||||
* void (*cmdq_notify)(struct jm_rdma_core *rdma, u32 event);
|
||||
* Notify new command to the related command queue.
|
||||
* For example:
|
||||
* iowrite32(event, cmd_db_reg); //cmd_db_reg = reg_addr + 0xEFC0
|
||||
*
|
||||
* int (*get_irqn)(struct jm_rdma_core *rdma, int index);
|
||||
* Get the irq number with the index.
|
||||
* For example:
|
||||
* return pci_irq_vector(ae_dev->pdev, index);
|
||||
*
|
||||
* int (*store_bond_info)(struct jm_rdma_core *rdma,
|
||||
* struct net_device *master, bool flag);
|
||||
* Currently an empty function(return 0) is ok.
|
||||
*
|
||||
* void (*get_bar)(struct jm_rdma_core *rdma, void **base, void **eq_reg);
|
||||
* Get BAR mapping bar address and eq address.
|
||||
* For example:
|
||||
* *base = reg_addr; // reg_addr = ioremap(base_base, 64 * 1024)
|
||||
* *eq_reg = eq_db_reg; // eq_db_reg = reg_addr + 0xF000
|
||||
*
|
||||
* void (*get_uar)(struct jm_rdma_core *rdma, phys_addr_t *base, u32 *len);
|
||||
* Get UAR base and length.
|
||||
* For example:
|
||||
* *base = uar_base; //bar_base + 64 * 1024
|
||||
* *len = uar_size; // 64 * 1024
|
||||
*
|
||||
* void (*get_vector)(struct jm_rdma_core *rdma, int num, int base);
|
||||
* Get the base and number of rdma's interrupt vector.
|
||||
* For example:
|
||||
* *base = vector_base;
|
||||
* *num = vector_num;
|
||||
*
|
||||
* void (*timer_db)(struct jm_rdma_core *rdma, u32 qpn, int flags);
|
||||
* Trigger a time DB.
|
||||
* Currently an empty function is ok.
|
||||
*
|
||||
* void (*reload)(struct jm_rdma_core *rdma);
|
||||
* Reload rdma core driver.
|
||||
* Currently an empty function is ok.
|
||||
*
|
||||
*/
|
||||
struct jm_rdma_ops {
|
||||
struct device *(*get_device)(struct jm_rdma_core *rdma);
|
||||
void (*get_dev_info)(struct jm_rdma_core *rdma, u8 *feature, u8 *rev_id,
|
||||
u16 *dev_id, u16 *vendor);
|
||||
void (*cmdq_notify)(struct jm_rdma_core *rdma, u32 event);
|
||||
int (*get_irqn)(struct jm_rdma_core *rdma, int index);
|
||||
int (*store_bond_info)(struct jm_rdma_core *rdma,
|
||||
struct net_device *master, bool flag);
|
||||
void (*get_bar)(struct jm_rdma_core *rdma, void **base, void **eq_reg);
|
||||
void (*get_uar)(struct jm_rdma_core *rdma, phys_addr_t *base, int *len);
|
||||
void (*get_vector)(struct jm_rdma_core *rdma, int *num, int *base);
|
||||
bool (*is_error)(struct jm_rdma_core *rdma);
|
||||
void (*timer_db)(struct jm_rdma_core *rdma, u32 qpn, int flags);
|
||||
void (*reload)(struct jm_rdma_core *rdma);
|
||||
};
|
||||
|
||||
struct jm_rdma_core {
|
||||
struct jm_rdma_ops *ops;
|
||||
struct jm_rdma_adev **adev;
|
||||
int adev_idx;
|
||||
};
|
||||
|
||||
struct jm_rdma_adev {
|
||||
struct auxiliary_device adev;
|
||||
struct jm_rdma_core *rdma_core;
|
||||
int idx;
|
||||
};
|
||||
|
||||
enum {
|
||||
JM_DEVICE_FEATURE_CMDQ_IS_PA = 1 << 0,
|
||||
JM_DEVICE_FEATURE_ATOMIC_HCA = 1 << 1,
|
||||
};
|
||||
|
||||
|
||||
#endif
|
@ -0,0 +1,239 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# Copyright (c) 2023, Jaguar Micro. All rights reserved
|
||||
#
|
||||
# Helper script to detect if auxiliary bus support. This script
|
||||
#
|
||||
# returns 0 when:
|
||||
# - CONFIG_AUXILIARY_BUS=y
|
||||
# - auxiliary_bus.h was found
|
||||
#
|
||||
# Returning 0 means the driver build/install doesn't need OOT
|
||||
# auxiliary bus
|
||||
#
|
||||
# returns 1 when:
|
||||
# - CONFIG_AUXILIARY_BUS=n (or any value that's not "=y")
|
||||
# - kernel configuration was incorrect
|
||||
# - kernel configuration file was not found
|
||||
#
|
||||
# Returning 1 means something bad/unexpected happened and the
|
||||
# driver build/install should treat this as a failure
|
||||
#
|
||||
# returns 2 when:
|
||||
# - When OOT auxiliary is needed regardless if a previous OOT
|
||||
# auxiliary was already. This is done because the driver
|
||||
# always needs to build against auxiliary.o to avoid
|
||||
# warnings/errors since auxiliary.o is built-in to the
|
||||
# driver's makefile
|
||||
#
|
||||
# Returning 2 means the driver build/install needs OOT auxiliary
|
||||
# bus
|
||||
#
|
||||
# returns 3 when:
|
||||
# - A file and/or directory does not exist
|
||||
#
|
||||
# Returning 3 means something bad/unexpected happened and the
|
||||
# driver build/install should treat this as a failure
|
||||
#
|
||||
# Note: when ksrc and build-kernel are both specified on the
|
||||
# command line and build-kernel is not in the same location
|
||||
# as ksrc, then ksrc takes precedence. For example:
|
||||
# ./check_aux_bus --ksrc=/lib/modules/5.8.0/source --build-kernel=5.10.0
|
||||
#
|
||||
# In this case the kernel config file won't be searched for and
|
||||
# the script will only check to see if the in-tree/OOT auxiliary_bus.h
|
||||
# file exists at ksrc.
|
||||
|
||||
msg()
|
||||
{
|
||||
if [ $verbose == 1 ]; then
|
||||
echo -e $1
|
||||
fi
|
||||
}
|
||||
|
||||
exit_builtin_auxiliary_enabled() { exit 0; }
|
||||
exit_kconfig_invalid() { exit 1; }
|
||||
exit_need_oot_auxiliary() { exit 2; }
|
||||
exit_not_found_failure() { exit 3; }
|
||||
|
||||
find_aux_bus_inc()
|
||||
{
|
||||
aux_bus_inc=$(find -L ${ksrc} -name "auxiliary_bus.h")
|
||||
msg "auxiliary_bus.h location: ${aux_bus_inc}"
|
||||
}
|
||||
|
||||
LINUX_INC_DIR="include/linux"
|
||||
|
||||
set_build_kernel()
|
||||
{
|
||||
build_kernel=$(uname -r)
|
||||
}
|
||||
|
||||
find_kernel_source()
|
||||
{
|
||||
# All the default places to look for kernel source
|
||||
test_dirs=(/lib/modules/${build_kernel}/source \
|
||||
/lib/modules/${build_kernel}/build \
|
||||
/usr/src/linux-${build_kernel} \
|
||||
/usr/src/linux-$(echo ${build_kernel} | sed 's/-.*//') \
|
||||
/usr/src/kernel-headers-${build_kernel} \
|
||||
/usr/src/kernel-source-${build_kernel} \
|
||||
/usr/src/linux-$(echo ${build_kernel} | sed 's/\([0-9]*\.[0-9]*\)\..*/\1/') \
|
||||
/usr/src/linux \
|
||||
/usr/src/kernels/${build_kernel} \
|
||||
/usr/src/kernels)
|
||||
|
||||
# Save the first valid kernel source path
|
||||
for dir in "${test_dirs[@]}"; do
|
||||
if [ -d ${dir}/${LINUX_INC_DIR} ]; then
|
||||
ksrc=${dir}
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -z ${ksrc} ]; then
|
||||
echo "*** Kernel header files not in any of the expected locations."
|
||||
echo "*** Install the appropriate kernel development package, e.g."
|
||||
echo "kernel-devel, for building kernel modules and try again"
|
||||
exit_not_found_failure
|
||||
fi
|
||||
}
|
||||
|
||||
find_config_file()
|
||||
{
|
||||
# only search for kernel .config file if build_kernel is pointing
|
||||
# in the same tree as ksrc (see not about ksrc and build_kernel
|
||||
# both set in the scripts header comment)
|
||||
if [[ "$ksrc" != *"/lib/modules/${build_kernel}"* ]]; then
|
||||
msg "ksrc=$ksrc not the same as location generated from"
|
||||
msg "build_kernel=\"/lib/modules/${build_kernel}\", "
|
||||
msg "not searching for kernel .config file"
|
||||
else
|
||||
kbuild_dir="/lib/modules/${build_kernel}/build"
|
||||
|
||||
file_locations=(${kbuild_dir}/include/generated/autoconf.h \
|
||||
${kbuild_dir}/include/linux/autoconf.h \
|
||||
/boot/bmlinux.autoconf.h)
|
||||
|
||||
for file in "${file_locations[@]}"; do
|
||||
if [ -f ${file} ]; then
|
||||
kconfig=${file}
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -z ${kconfig} ]; then
|
||||
msg "Kernel config file not found at any of the expected locations."
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
get_config_auxiliary_bus()
|
||||
{
|
||||
# CONFIG_AUXILIARY_BUS=0 corresponds to CONFIG_AUXILIARY_BUS=n
|
||||
# CONFIG_AUXILIARY_BUS=1 corresponds to CONFIG_AUXILIARY_BUS=y
|
||||
# CONFIG_AUXILIARY_BUS= corresponds to CONFIG_AUXILIARY_BUS not available in the kernel
|
||||
CONFIG_AUXILIARY_BUS=$(grep CONFIG_AUXILIARY_BUS ${kconfig} | awk -F" " '{print $3}')
|
||||
msg "CONFIG_AUXILIARY_BUS=${CONFIG_AUXILIARY_BUS}"
|
||||
}
|
||||
|
||||
ksrc=""
|
||||
build_kernel=""
|
||||
verbose=0
|
||||
|
||||
usage()
|
||||
{
|
||||
script=$(basename $0)
|
||||
echo -e "usage:"
|
||||
echo -e "\t$script [options]"
|
||||
echo -e "\n\toptions:"
|
||||
echo -e "\t -v, --verbose"
|
||||
echo -e "\t -h, --help"
|
||||
echo -e "\n\turn script against specified kernel source"
|
||||
echo -e "\t -k, --ksrc \"/lib/modules/5.12.0/source\""
|
||||
echo -e "\n\turn script with kernel version (kernel version used to"
|
||||
echo -e "find kernel source programatically)"
|
||||
echo -e "\t -b, --build-kernel \"5.8.0\""
|
||||
}
|
||||
|
||||
options=$(getopt -o "k:b:vh" --long ksrc:,build-kernel:,verbose,help -- "$@")
|
||||
eval set -- "$options"
|
||||
while :; do
|
||||
case $1 in
|
||||
-k|--ksrc) ksrc=$2; shift;;
|
||||
-b|--build-kernel) build_kernel=$2; shift;;
|
||||
-v|--verbose) verbose=1 ;;
|
||||
-h|--help) usage && exit 0;;
|
||||
--) shift; break;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [ $verbose == 1 ]; then
|
||||
set -x
|
||||
fi
|
||||
|
||||
# both build_kernel and ksrc are unset so programatically determine build_kernel
|
||||
if [ -z $build_kernel ] && [ -z $ksrc ]; then
|
||||
set_build_kernel
|
||||
fi
|
||||
|
||||
# only programatically search for kernel source if ksrc not set on command line
|
||||
if [ -z $ksrc ]; then
|
||||
find_kernel_source
|
||||
fi
|
||||
|
||||
find_config_file
|
||||
|
||||
if [ ! -z $kconfig ]; then
|
||||
# if we found the kernel .config file then exit the script based on various
|
||||
# conditions that depend on the CONFIG_AUXILIARY_BUS string being found
|
||||
get_config_auxiliary_bus
|
||||
|
||||
if [ -z "$CONFIG_AUXILIARY_BUS" ]; then
|
||||
msg "CONFIG_AUXILIARY_BUS not found in ${kconfig}."
|
||||
# CONFIG_AUXILIARY_BUS string was not found, so OOT auxiliary is needed
|
||||
exit_need_oot_auxiliary
|
||||
elif [ "$CONFIG_AUXILIARY_BUS" = "1" ]; then
|
||||
msg "CONFIG_AUXILIARY_BUS=y in ${kconfig}."
|
||||
# CONFIG_AUXILIARY_BUS=y, so OOT auxiliary is not needed
|
||||
exit_builtin_auxiliary_enabled
|
||||
else
|
||||
msg ""
|
||||
msg "kernel $build_kernel supports auxiliary bus, but CONFIG_AUXILIARY_BUS"
|
||||
msg "is not set in ${kconfig}. Rebuild your kernel with"
|
||||
msg "CONFIG_AUXILIARY_BUS=y"
|
||||
msg ""
|
||||
# CONFIG_AUXILIARY_BUS is not "=y", but the string was found, so report
|
||||
# the failure so it can be used to fail build/install
|
||||
exit_kconfig_invalid
|
||||
fi
|
||||
else
|
||||
if [ ! -d ${ksrc}/${LINUX_INC_DIR} ] && [ ! -d ${ksrc}/source/${LINUX_INC_DIR} ]; then
|
||||
echo "${ksrc}/${LINUX_INC_DIR} and ${ksrc}/source/${LINUX_INC_DIR}"
|
||||
echo "do not exist"
|
||||
exit_not_found_failure
|
||||
fi
|
||||
|
||||
# We didn't find a kernel .config file, so check to see if auxiliary_bus.h
|
||||
# is found in the kernel source include directory
|
||||
find_aux_bus_inc
|
||||
|
||||
if [ -f "$aux_bus_inc" ]; then
|
||||
# AUXILIARY_MODULE_PREFIX is defined only in out-of-tree auxiliary bus
|
||||
if [ $(grep -c AUXILIARY_MODULE_PREFIX $aux_bus_inc) -eq 0 ]; then
|
||||
msg "in-tree auxiliary_bus.h found at ${ksrc}/${LINUX_INC_DIR}"
|
||||
# If auxiliary_bus.h is included at ${ksrc} and it isn't our OOT version,
|
||||
#then don't build OOT auxiliary as part of the driver makefile
|
||||
exit_builtin_auxiliary_enabled
|
||||
else
|
||||
msg "OOT auxiliary_bus.h found at ${ksrc}/${LINUX_INC_DIR}"
|
||||
# If auxiliary bus is included at ${ksrc} and it is our OOT version, then
|
||||
# build OOT auxiliary as part of the driver makefile
|
||||
exit_need_oot_auxiliary
|
||||
fi
|
||||
else
|
||||
msg "auxiliary_bus.h not found at ${ksrc}/${LINUX_INC_DIR}"
|
||||
exit_need_oot_auxiliary
|
||||
fi
|
||||
fi
|
@ -0,0 +1,29 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# ccflags-y += -DCONFIG_NOSIM_DEBUG
|
||||
obj-m := crete_pnic.o
|
||||
crete_pnic-objs := crete_nic_main.o \
|
||||
crete_nic_io.o \
|
||||
crete_nic.o \
|
||||
crete_nic_ethtool.o
|
||||
KERNELDIR ?= /lib/modules/$(shell uname -r)/build/
|
||||
|
||||
#################
|
||||
# Auxiliary Bus #
|
||||
# #################
|
||||
|
||||
AUX_BUS_SYM := /lib/modules/$(shell uname -r)/extern-symvers/jm_auxiliary.symvers
|
||||
|
||||
ifeq ($(wildcard $(AUX_BUS_SYM)),)
|
||||
$(info ${AUX_BUS_SYM} File does not exist)
|
||||
else
|
||||
KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/jm_auxiliary.symvers
|
||||
endif
|
||||
|
||||
KBUILD_EXTRA_SYMBOLS += $(PWD)/../crete-core/Module.symvers
|
||||
|
||||
all:
|
||||
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
|
||||
clean:
|
||||
@\rm *.o *.ko *.mod.c modules.order .*.mod Module.symvers crete_core.mod *.mod .*.cmd .tmp_versions .crete* -rf
|
||||
|
||||
|
@ -0,0 +1,203 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* JaguarMicro virtual dev driver for virtio dataplane offloading
|
||||
*
|
||||
* Copyright (C) 2022 JaguarMicro Corporation.
|
||||
*
|
||||
* Author: Angus Chen <angus.chen@jaguarmicro.com>
|
||||
*
|
||||
*/
|
||||
#include <linux/vdpa.h>
|
||||
#include "../crete-core/crete_cmd_if.h"
|
||||
#include "crete_nic.h"
|
||||
|
||||
void crete_vnic_priv_cleanup(struct crete_vnic_priv *priv)
|
||||
{
|
||||
struct crete_core_dev *core_dev = priv->coredev;
|
||||
struct pci_dev *pdev;
|
||||
struct crete_net_common_cfg *netcfg = &priv->net_cfg;
|
||||
|
||||
if (!priv->coredev)
|
||||
return;
|
||||
|
||||
pdev = core_dev->pdev;
|
||||
dev_err(&pdev->dev, "enter crete_priv_cleanup\n");
|
||||
|
||||
kfree(netcfg->mc_list);
|
||||
netcfg->mc_list = NULL;
|
||||
|
||||
kfree(netcfg->uc_list);
|
||||
netcfg->uc_list = NULL;
|
||||
|
||||
// memset(priv, 0, sizeof(*priv));
|
||||
dev_err(&pdev->dev, "exit crete_priv_cleanup\n");
|
||||
}
|
||||
|
||||
int crete_nic_set_device_type(struct crete_core_dev *core_dev, enum crete_dev_type op)
|
||||
{
|
||||
|
||||
int ret;
|
||||
struct pci_dev *pdev = core_dev->pdev;
|
||||
u32 devtype = 0;
|
||||
|
||||
ret = crete_set_dev_type(core_dev, op);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"Failed to set device type %x, set cmd error\n", op);
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = crete_get_dev_type(core_dev, &devtype);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "set dev type failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (devtype != op) {
|
||||
dev_err(&pdev->dev,
|
||||
" dev type not right check failed. dev type %x\n", op);
|
||||
goto out;
|
||||
}
|
||||
|
||||
return ret;
|
||||
out:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
u64 crete_net_get_supported_features(struct crete_core_dev *core_dev,
|
||||
enum crete_feature_opcode op)
|
||||
{
|
||||
|
||||
struct pci_dev *pdev = core_dev->pdev;
|
||||
u64 dev_features;
|
||||
u64 ret;
|
||||
|
||||
ret = crete_cmd_get_features(core_dev, op, &dev_features);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "get device features is error\n");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
core_dev->cap.hw_features = dev_features;
|
||||
dev_info(&pdev->dev, "device supported features[0x%llx]\n",
|
||||
core_dev->cap.hw_features);
|
||||
return ret;
|
||||
}
|
||||
|
||||
u64 crete_net_get_max_supported_vqs(struct crete_core_dev *core_dev)
|
||||
{
|
||||
int ret;
|
||||
u16 max_queue_size;
|
||||
u8 max_qp_num;
|
||||
u8 ctrl_queue_size;
|
||||
struct pci_dev *pdev = core_dev->pdev;
|
||||
|
||||
ret =
|
||||
crete_get_qp_cap(core_dev, &max_queue_size, &max_qp_num,
|
||||
&ctrl_queue_size);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "%s is error\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
core_dev->cap.qpcap.ctrl_queue_size = ctrl_queue_size;
|
||||
core_dev->cap.qpcap.max_qp_num = max_qp_num;
|
||||
core_dev->cap.qpcap.max_queue_size = max_queue_size;
|
||||
|
||||
dev_info(&pdev->dev,
|
||||
"crete vqs: ctl_qlen[0x%x] ioqlen[0x%x] maxvqs[%d]\n",
|
||||
ctrl_queue_size, max_queue_size, max_qp_num);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//todo: keyi cmd_if
|
||||
|
||||
int crete_trim_rings(struct crete_core_dev *cdev)
|
||||
{
|
||||
int cpunums = num_online_cpus();
|
||||
int maxqpnums = cdev->cap.qpcap.max_qp_num;
|
||||
|
||||
if (maxqpnums > CRETE_VNIC_MAX_QUEUES) {
|
||||
cdev->cap.qpcap.max_qp_num = CRETE_VNIC_MAX_QUEUES;
|
||||
crete_err(cdev->device, "max qp greater than %d\n",
|
||||
CRETE_VNIC_MAX_QUEUES);
|
||||
}
|
||||
cdev->ring_size = min(cpunums, maxqpnums);
|
||||
if (!cdev->ring_size) {
|
||||
crete_err(cdev->device, "ring size zero not right\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
} //todo: keyi cmd_if
|
||||
|
||||
int crete_vnic_priv_init(struct crete_vnic_priv *priv,
|
||||
struct net_device *netdev,
|
||||
struct crete_core_dev *core_dev)
|
||||
{
|
||||
int mem_size = (CRETE_MAX_UC_ADDRS - 1) * ETH_ALEN;
|
||||
struct crete_net_common_cfg *netcfg = &priv->net_cfg;
|
||||
int rc = 0;
|
||||
|
||||
priv->coredev = core_dev;
|
||||
priv->netdev = netdev;
|
||||
|
||||
netcfg->uc_list = kmalloc(mem_size, GFP_KERNEL);
|
||||
if (!netcfg->uc_list) {
|
||||
rc = -ENOMEM;
|
||||
goto err_uc_list_alloc;
|
||||
}
|
||||
netcfg->mc_list_size = CRETE_MAX_MC_ADDRS * ETH_ALEN;
|
||||
netcfg->mc_list = kmalloc(netcfg->mc_list_size, GFP_KERNEL);
|
||||
if (!netcfg->mc_list) {
|
||||
rc = -ENOMEM;
|
||||
goto err_mc_list_alloc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err_mc_list_alloc:
|
||||
kfree(netcfg->uc_list);
|
||||
netcfg->uc_list = NULL;
|
||||
err_uc_list_alloc:
|
||||
return rc;
|
||||
} //todo: keyi cmd_if
|
||||
|
||||
struct net_device *crete_vnic_create_netdev(struct crete_core_dev *coredev)
|
||||
{
|
||||
struct net_device *netdev;
|
||||
unsigned int txqs, rxqs;
|
||||
struct crete_vnic_priv *priv;
|
||||
struct pci_dev *pdev = coredev->pdev;
|
||||
int err;
|
||||
|
||||
txqs = coredev->ring_size;
|
||||
rxqs = coredev->ring_size;
|
||||
/* crete netdevice with max qp number */
|
||||
netdev = alloc_etherdev_mqs(sizeof(struct crete_vnic_priv), txqs, rxqs);
|
||||
if (!netdev) {
|
||||
dev_err(&pdev->dev, "alloc_etherdev_mqs() failed\n");
|
||||
return NULL;
|
||||
}
|
||||
priv = netdev_priv(netdev);
|
||||
coredev->netdev = netdev;
|
||||
err = crete_vnic_priv_init(priv, netdev, coredev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "crete_vnic_priv_init failed\n");
|
||||
goto err_priv_init;
|
||||
}
|
||||
|
||||
netif_tx_disable(netdev);
|
||||
return netdev;
|
||||
|
||||
err_priv_init:
|
||||
free_netdev(netdev);
|
||||
return NULL;
|
||||
} //todo: keyi cmd_if
|
||||
|
||||
void crete_build_common_netdev(struct net_device *netdev)
|
||||
{
|
||||
struct crete_vnic_priv *priv = netdev_priv(netdev);
|
||||
struct crete_core_dev *core_dev = priv->coredev;
|
||||
struct pci_dev *pdev = core_dev->pdev;
|
||||
|
||||
netdev->watchdog_timeo = 5 * HZ;
|
||||
strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
|
||||
SET_NETDEV_DEV(netdev, &pdev->dev);
|
||||
strcpy(netdev->name, "eth%d");
|
||||
}
|
@ -0,0 +1,237 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* JaguarMicro virt device driver for virtio dataplane offloading
|
||||
*
|
||||
* Copyright (C) 2020 JaguarMicro Corporation.
|
||||
*/
|
||||
|
||||
#ifndef _CRETE_NIC_H_
|
||||
#define _CRETE_NIC_H_
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pci_regs.h>
|
||||
#include <uapi/linux/virtio_net.h>
|
||||
#include <uapi/linux/virtio_config.h>
|
||||
#include <uapi/linux/virtio_pci.h>
|
||||
#include <linux/auxiliary_bus.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/virtio.h>
|
||||
#include <linux/virtio_net.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/average.h>
|
||||
#include <linux/filter.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include "../crete-core/crete_cmd.h"
|
||||
#include "../crete-core/crete_cmd_if.h"
|
||||
/* Max 8 data queue pairs(16 queues) and one control vq for now. */
|
||||
#define CRETE_VNIC_MAX_QUEUES 17
|
||||
#define CRETE_VNIC_QUEUES_NOCTRL 16
|
||||
|
||||
#define CRETE_VNIC_QUEUE_ALIGNMENT PAGE_SIZE
|
||||
/*attention pls ,it's the depth of queue*/
|
||||
#define CRETE_VNIC_QUEUE_SIZE_MAX 512
|
||||
#define CRETE_VNIC_QUEUE_SIZE_MIN 64
|
||||
#define CRETE_VNIC_MSI_CONFIG_OFF 0
|
||||
#define CRETE_VNIC_MSI_QUEUE_OFF 1
|
||||
#define CRETE_VNIC_PCI_MAX_RESOURCE 6
|
||||
#define VHOST_F_LOG_ALL 26
|
||||
#define VHOST_ACCESS_WO 0x2
|
||||
#define DEBUG
|
||||
|
||||
#define VIRTIO_NET_CONFIG_OFFSET_MAC offsetof(struct virtio_net_config, mac)
|
||||
#define VIRTIO_NET_CONFIG_OFFSET_MTU offsetof(struct virtio_net_config, mtu)
|
||||
|
||||
/**********************************vnic add******************************************/
|
||||
#define CRETE_VNIC_MQ_MAX 17
|
||||
|
||||
#define CRETE_VNIC_AUX_DEV_NAME "crete_core.nic"
|
||||
#define CRETE_NIC_DRV_NAME "crete_pnic"
|
||||
/* FIXME: MTU in config. */
|
||||
#define GOOD_PACKET_LEN (ETH_HLEN + VLAN_HLEN + ETH_DATA_LEN)
|
||||
#define GOOD_COPY_LEN 128
|
||||
|
||||
#define VIRTNET_RX_PAD (NET_IP_ALIGN + NET_SKB_PAD)
|
||||
|
||||
/* Amount of XDP headroom to prepend to packets for use by xdp_adjust_head */
|
||||
#define VIRTIO_XDP_HEADROOM 256
|
||||
|
||||
/* RX packet size EWMA. The average packet size is used to determine the packet
|
||||
* buffer size when refilling RX rings. As the entire RX ring may be refilled
|
||||
* at once, the weight is chosen so that the EWMA will be insensitive to short-
|
||||
* term, transient changes in packet size.
|
||||
*/
|
||||
DECLARE_EWMA(pkt_len, 0, 64)
|
||||
#define GUEST_OFFLOAD_GRO_HW_MASK ((1ULL << VIRTIO_NET_F_GUEST_TSO4) | \
|
||||
(1ULL << VIRTIO_NET_F_GUEST_TSO6) | \
|
||||
(1ULL << VIRTIO_NET_F_GUEST_ECN) | \
|
||||
(1ULL << VIRTIO_NET_F_GUEST_UFO))
|
||||
|
||||
struct crete_vnic_stat_desc {
|
||||
char desc[ETH_GSTRING_LEN];
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
struct crete_vnic_sq_stats {
|
||||
struct u64_stats_sync syncp;
|
||||
u64 packets;
|
||||
u64 bytes;
|
||||
u64 xdp_tx;
|
||||
u64 xdp_tx_drops;
|
||||
u64 kicks;
|
||||
};
|
||||
|
||||
struct crete_vnic_rq_stats {
|
||||
struct u64_stats_sync syncp;
|
||||
u64 packets;
|
||||
u64 bytes;
|
||||
u64 drops;
|
||||
u64 xdp_packets;
|
||||
u64 xdp_tx;
|
||||
u64 xdp_redirects;
|
||||
u64 xdp_drops;
|
||||
u64 kicks;
|
||||
};
|
||||
|
||||
#define CRETE_VNIC_SQ_STAT(m) offsetof(struct crete_vnic_sq_stats, m)
|
||||
#define CRETE_VNIC_RQ_STAT(m) offsetof(struct crete_vnic_rq_stats, m)
|
||||
|
||||
struct send_queue {
|
||||
/* Virtqueue associated with this send _queue */
|
||||
struct virtqueue *vq;
|
||||
|
||||
/* TX: fragments + linear part + virtio header */
|
||||
struct scatterlist sg[MAX_SKB_FRAGS + 2];
|
||||
|
||||
/* Name of the send queue: output.$index */
|
||||
char name[40];
|
||||
|
||||
struct crete_vnic_sq_stats stats;
|
||||
|
||||
struct napi_struct napi;
|
||||
};
|
||||
|
||||
/* Internal representation of a receive virtqueue */
|
||||
struct receive_queue {
|
||||
/* Virtqueue associated with this receive_queue */
|
||||
struct virtqueue *vq;
|
||||
|
||||
struct napi_struct napi;
|
||||
|
||||
struct bpf_prog __rcu *xdp_prog;
|
||||
|
||||
struct crete_vnic_rq_stats stats;
|
||||
|
||||
/* Chain pages by the private ptr. */
|
||||
struct page *pages;
|
||||
|
||||
/* Average packet length for mergeable receive buffers. */
|
||||
struct ewma_pkt_len mrg_avg_pkt_len;
|
||||
|
||||
/* Page frag for packet buffer allocation. */
|
||||
struct page_frag alloc_frag;
|
||||
|
||||
/* RX: fragments + linear part + virtio header */
|
||||
struct scatterlist sg[MAX_SKB_FRAGS + 2];
|
||||
|
||||
/* Min single buffer size for mergeable buffers case. */
|
||||
unsigned int min_buf_len;
|
||||
|
||||
/* Name of this receive queue: input.$index */
|
||||
char name[40];
|
||||
};
|
||||
|
||||
struct crete_vnic_msix_info {
|
||||
struct virtqueue *vq;
|
||||
int qid;
|
||||
/* MSI-X vector (or none) */
|
||||
unsigned int msix_vector;
|
||||
unsigned int irq;
|
||||
bool ready;
|
||||
char msix_name[256];
|
||||
};
|
||||
|
||||
struct crete_net_common_cfg {
|
||||
u32 rx_mask;
|
||||
u16 uc_filter_count;
|
||||
u8 *uc_list;
|
||||
u8 *mc_list;
|
||||
int mc_list_size;
|
||||
int mc_list_count;
|
||||
__u16 vportid;
|
||||
__u8 mac[ETH_ALEN];
|
||||
__u16 mtu;
|
||||
__le32 speed;
|
||||
/*
|
||||
* 0x00 - half duplex
|
||||
* 0x01 - full duplex
|
||||
* Any other value stands for unknown.
|
||||
*/
|
||||
__u8 duplex;
|
||||
/* maximum size of RSS key */
|
||||
__u8 rss_max_key_size;
|
||||
/* maximum number of indirection table entries */
|
||||
__le16 rss_max_indirection_table_length;
|
||||
/* bitmask of supported VIRTIO_NET_RSS_HASH_ types */
|
||||
__le32 supported_hash_types;
|
||||
__le16 vlanid;
|
||||
};
|
||||
|
||||
struct crete_vnic_priv {
|
||||
struct virtio_device vdev;
|
||||
struct crete_core_dev *coredev;
|
||||
struct net_device *netdev;
|
||||
struct send_queue *sq;
|
||||
struct receive_queue *rq;
|
||||
unsigned int status;
|
||||
u16 max_queue_pairs;
|
||||
u16 curr_queue_pairs;
|
||||
bool big_packets;
|
||||
bool mergeable_rx_bufs;
|
||||
bool any_header_sg;
|
||||
u8 hdr_len;
|
||||
struct delayed_work refill;
|
||||
bool refill_enabled;
|
||||
spinlock_t refill_lock;
|
||||
bool affinity_hint_set;
|
||||
struct hlist_node node;
|
||||
struct hlist_node node_dead;
|
||||
unsigned long guest_offloads;
|
||||
unsigned long guest_offloads_capable;
|
||||
spinlock_t lock;
|
||||
struct crete_vnic_msix_info msix_info[CRETE_VNIC_MQ_MAX];
|
||||
struct crete_net_common_cfg net_cfg;
|
||||
struct crete_nb cnb;
|
||||
struct work_struct set_rx_mode_work;
|
||||
struct workqueue_struct *wq;
|
||||
};
|
||||
|
||||
/*******************************************************************************/
|
||||
enum crete_net_status {
|
||||
CRETE_NET_DEV_STARTUP,
|
||||
CRETE_NET_DEV_FEATURE_OK,
|
||||
CRETE_NET_DEV_DEV_OK,
|
||||
CRETE_NET_DEV_STOPPED
|
||||
};
|
||||
|
||||
#define CRETE_RX_SEQ 0
|
||||
#define CRETE_TX_SEQ 1
|
||||
|
||||
int crete_nic_set_hwstatus(struct crete_core_dev *core_dev, u8 status);
|
||||
int crete_nic_set_device_type(struct crete_core_dev *core_dev,
|
||||
enum crete_dev_type op);
|
||||
int crete_trim_rings(struct crete_core_dev *core_dev);
|
||||
struct net_device *crete_vnic_create_netdev(struct crete_core_dev *core_dev);
|
||||
void crete_build_common_netdev(struct net_device *netdev);
|
||||
void crete_vnic_destroy_netdev(struct net_device *netdev);
|
||||
void crete_vnic_priv_cleanup(struct crete_vnic_priv *priv);
|
||||
u64 crete_net_get_max_supported_vqs(struct crete_core_dev *core_dev);
|
||||
u64 crete_net_get_supported_features(struct crete_core_dev *core_dev,
|
||||
enum crete_feature_opcode op);
|
||||
#endif /* _CRETE_NIC_H_ */
|
@ -0,0 +1,516 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/* A network driver using virtio.
|
||||
*
|
||||
* Copyright 2007 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation
|
||||
*/
|
||||
//#define DEBUG
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/virtio.h>
|
||||
#include <linux/virtio_net.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/bpf_trace.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/average.h>
|
||||
#include <linux/filter.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <net/route.h>
|
||||
#include <net/xdp.h>
|
||||
#include <net/net_failover.h>
|
||||
#include "crete_nic.h"
|
||||
#include "crete_nic_io.h"
|
||||
#include <linux/firmware.h>
|
||||
#include "../crete-core/crete_fw_update.h"
|
||||
|
||||
#define CRETE_VNIC_DRIVER_VERSION "crete-vnic-1.0"
|
||||
/******************net tools****************************/
|
||||
static void crete_vnic_get_drvinfo(struct net_device *dev,
|
||||
struct ethtool_drvinfo *info)
|
||||
{
|
||||
struct crete_vnic_priv *vnic_priv = netdev_priv(dev);
|
||||
struct crete_core_dev *core_dev = vnic_priv->coredev;
|
||||
struct pci_dev *pdev = core_dev->pdev;
|
||||
|
||||
strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
|
||||
|
||||
snprintf(info->fw_version, sizeof(info->fw_version),
|
||||
"%d.%d.%d.%d", fw_ver_maj(core_dev),
|
||||
fw_ver_min(core_dev), fw_ver_sub(core_dev), fw_ver_rev(core_dev));
|
||||
|
||||
strlcpy(info->version, CRETE_VNIC_DRIVER_VERSION,
|
||||
sizeof(info->version));
|
||||
strlcpy(info->bus_info, pci_name(pdev), sizeof(info->bus_info));
|
||||
}
|
||||
|
||||
static u32 crete_vnic_get_link(struct net_device *netdev)
|
||||
{
|
||||
//struct crete_vnic_priv *vnic_priv = netdev_priv(netdev);
|
||||
//struct crete_core_dev *core_dev =vnic_priv->coredev;
|
||||
/* If the link is not reported up to netdev, interrupts are disabled,
|
||||
* and so the physical link state may have changed since we last
|
||||
* looked. Set get_link_status to make sure that the true link
|
||||
* state is interrogated, rather than pulling a cached and possibly
|
||||
* stale link state from the driver.
|
||||
*/
|
||||
if (!netif_carrier_ok(netdev)) {
|
||||
/*todo to vdev get link status */
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* about the anolis 5.10.134-14 kernel version
|
||||
* auxliary define with return int value
|
||||
*/
|
||||
#if defined(SNIC_ANOLIS_VERSION14) || !defined(CONFIG_ETHTOOL_EXTEND_RINGPARAM)
|
||||
static void crete_vnic_get_ringparam(struct net_device *dev,
|
||||
struct ethtool_ringparam *ring)
|
||||
{
|
||||
struct crete_vnic_priv *vnic_priv = netdev_priv(dev);
|
||||
|
||||
ring->rx_max_pending = virtqueue_get_vring_size(vnic_priv->rq[0].vq);
|
||||
ring->tx_max_pending = virtqueue_get_vring_size(vnic_priv->sq[0].vq);
|
||||
ring->rx_pending = ring->rx_max_pending;
|
||||
ring->tx_pending = ring->tx_max_pending;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void crete_vnic_get_ringparam(struct net_device *dev,
|
||||
struct ethtool_ringparam *ring,
|
||||
struct kernel_ethtool_ringparam
|
||||
*kernel_ring,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct crete_vnic_priv *vnic_priv = netdev_priv(dev);
|
||||
|
||||
ring->rx_max_pending = virtqueue_get_vring_size(vnic_priv->rq[0].vq);
|
||||
ring->tx_max_pending = virtqueue_get_vring_size(vnic_priv->sq[0].vq);
|
||||
ring->rx_pending = ring->rx_max_pending;
|
||||
ring->tx_pending = ring->tx_max_pending;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void crete_vnic_get_channels(struct net_device *dev,
|
||||
struct ethtool_channels *channels)
|
||||
{
|
||||
struct crete_vnic_priv *vnic_priv = netdev_priv(dev);
|
||||
|
||||
channels->combined_count = vnic_priv->curr_queue_pairs;
|
||||
channels->max_combined = vnic_priv->max_queue_pairs;
|
||||
channels->max_other = 0;
|
||||
channels->rx_count = 0;
|
||||
channels->tx_count = 0;
|
||||
channels->other_count = 0;
|
||||
}
|
||||
|
||||
/* TODO: Eliminate OOO packets during switching */
|
||||
static int crete_vnic_set_channels(struct net_device *dev,
|
||||
struct ethtool_channels *channels)
|
||||
{
|
||||
struct crete_vnic_priv *vnic_priv = netdev_priv(dev);
|
||||
u16 queue_pairs = channels->combined_count;
|
||||
int err;
|
||||
|
||||
/* We don't support separate rx/tx channels.
|
||||
* We don't allow setting 'other' channels.
|
||||
*/
|
||||
if (channels->rx_count || channels->tx_count || channels->other_count)
|
||||
return -EINVAL;
|
||||
|
||||
if (queue_pairs > vnic_priv->max_queue_pairs || queue_pairs == 0)
|
||||
return -EINVAL;
|
||||
|
||||
err = __crete_vnic_set_queues(dev, queue_pairs);
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
netif_set_real_num_tx_queues(dev, queue_pairs);
|
||||
netif_set_real_num_rx_queues(dev, queue_pairs);
|
||||
err:
|
||||
return err;
|
||||
}
|
||||
|
||||
int crete_vnic_ethtool_flash_device(struct crete_vnic_priv *vnic_priv,
|
||||
struct ethtool_flash *flash)
|
||||
{
|
||||
struct crete_core_dev *cdev = vnic_priv->coredev;
|
||||
struct net_device *dev = vnic_priv->netdev;
|
||||
const struct firmware *fw;
|
||||
int err;
|
||||
|
||||
if (flash->region != ETHTOOL_FLASH_ALL_REGIONS)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
err = request_firmware_direct(&fw, flash->data, &dev->dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
dev_hold(dev);
|
||||
rtnl_unlock();
|
||||
|
||||
err = crete_firmware_flash(cdev, fw, NULL, CRETE_FWU_ETHTOOL);
|
||||
release_firmware(fw);
|
||||
|
||||
rtnl_lock();
|
||||
dev_put(dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int crete_vnic_flash_device(struct net_device *dev,
|
||||
struct ethtool_flash *flash)
|
||||
{
|
||||
struct crete_vnic_priv *vnic_priv = netdev_priv(dev);
|
||||
|
||||
return crete_vnic_ethtool_flash_device(vnic_priv, flash);
|
||||
}
|
||||
|
||||
struct ptys2ethtool_config {
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(supported);
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(advertised);
|
||||
};
|
||||
|
||||
static
|
||||
struct ptys2ethtool_config ptys2ethtool_table[CRETE_LINK_MODES_CAP_BIT];
|
||||
|
||||
#define CRETE_BUILD_PTYS2ETHTOOL_CONFIG(reg_, table, ...) \
|
||||
({ \
|
||||
struct ptys2ethtool_config *cfg; \
|
||||
const unsigned int modes[] = { __VA_ARGS__ }; \
|
||||
unsigned int i, bit, idx; \
|
||||
cfg = &table[reg_]; \
|
||||
bitmap_zero(cfg->supported, \
|
||||
__ETHTOOL_LINK_MODE_MASK_NBITS); \
|
||||
bitmap_zero(cfg->advertised, \
|
||||
__ETHTOOL_LINK_MODE_MASK_NBITS); \
|
||||
for (i = 0 ; i < ARRAY_SIZE(modes) ; ++i) { \
|
||||
bit = modes[i] % 64; \
|
||||
idx = modes[i] / 64; \
|
||||
__set_bit(bit, &cfg->supported[idx]); \
|
||||
__set_bit(bit, &cfg->advertised[idx]); \
|
||||
} \
|
||||
})
|
||||
|
||||
void crete_build_ptys2ethtool_map(void)
|
||||
{
|
||||
memset(ptys2ethtool_table, 0, sizeof(ptys2ethtool_table));
|
||||
CRETE_BUILD_PTYS2ETHTOOL_CONFIG(CRETE_10GBASE_BIT, ptys2ethtool_table,
|
||||
ETHTOOL_LINK_MODE_10000baseR_FEC_BIT,
|
||||
ETHTOOL_LINK_MODE_10000baseCR_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_10000baseLR_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_10000baseER_Full_BIT);
|
||||
CRETE_BUILD_PTYS2ETHTOOL_CONFIG(CRETE_25GBASE_BIT, ptys2ethtool_table,
|
||||
ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_25000baseSR_Full_BIT);
|
||||
CRETE_BUILD_PTYS2ETHTOOL_CONFIG(CRETE_40GBASE_BIT, ptys2ethtool_table,
|
||||
ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT);
|
||||
CRETE_BUILD_PTYS2ETHTOOL_CONFIG(CRETE_50GBASE_BIT, ptys2ethtool_table,
|
||||
ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT);
|
||||
CRETE_BUILD_PTYS2ETHTOOL_CONFIG(CRETE_100GBASE_BIT, ptys2ethtool_table,
|
||||
ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT);
|
||||
CRETE_BUILD_PTYS2ETHTOOL_CONFIG(CRETE_200GBASE_BIT, ptys2ethtool_table,
|
||||
ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_200000baseSR2_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_200000baseLR2_ER2_FR2_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_200000baseDR2_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_200000baseCR2_Full_BIT);
|
||||
CRETE_BUILD_PTYS2ETHTOOL_CONFIG(CRETE_400GBASE_BIT, ptys2ethtool_table,
|
||||
ETHTOOL_LINK_MODE_400000baseSR8_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_400000baseLR8_ER8_FR8_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_400000baseDR8_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_400000baseCR8_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_400000baseSR4_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_400000baseLR4_ER4_FR4_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_400000baseDR4_Full_BIT,
|
||||
ETHTOOL_LINK_MODE_400000baseCR4_Full_BIT);
|
||||
}
|
||||
|
||||
u16 crete_port_speed2linkmode(u32 speed)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(crete_link_speed); ++i) {
|
||||
if (crete_link_speed[i] == speed)
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crete_ethtool_set_link_ksettings(struct crete_vnic_priv *vnic_priv,
|
||||
const struct ethtool_link_ksettings *link_ksettings)
|
||||
{
|
||||
struct crete_core_dev *cdev = vnic_priv->coredev;
|
||||
const struct ethtool_link_settings *base = &link_ksettings->base;
|
||||
struct net_device *dev = vnic_priv->netdev;
|
||||
struct crete_speed_duplex sd_current = {0};
|
||||
u16 change_bit = 0;
|
||||
u16 link_mode;
|
||||
int ret;
|
||||
|
||||
if (base->autoneg == AUTONEG_ENABLE) {
|
||||
netdev_err(dev, "Autonegotiation is not supported!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (base->duplex != DUPLEX_FULL) {
|
||||
netdev_err(dev, "Only full duplex mode is supported!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
link_mode = crete_port_speed2linkmode(base->speed);
|
||||
if (link_mode >= CRETE_LINK_MODES_NUMBER || link_mode < CRETE_10GBASE) {
|
||||
netdev_err(dev, "speed parameter is illeagl.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = crete_get_port_speed_duplex(cdev, &sd_current);
|
||||
if (ret) {
|
||||
netdev_err(dev, "Failed to get current speed and duplex mode!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (sd_current.speed == link_mode && sd_current.duplex == base->duplex) {
|
||||
netdev_info(dev, "Speed and duplex mode are already set to the requested values.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
change_bit |= (sd_current.speed != link_mode) ? LINK_SPEED_OP_BIT : 0;
|
||||
change_bit |= (sd_current.duplex != base->duplex) ? DUPLEX_MODE_OP_BIT : 0;
|
||||
|
||||
if (!netif_running(dev)) {
|
||||
netdev_err(dev, "Network interface is not running. Cannot change settings.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = crete_set_port_speed_duplex(cdev, link_mode, base->duplex, change_bit);
|
||||
if (ret) {
|
||||
netdev_err(dev, "Failed to set speed and duplex mode!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
netdev_info(dev, "Speed set to %d Mbps, duplex mode set to full.\n", base->speed);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int crete_vnic_set_link_ksettings(struct net_device *dev,
|
||||
const struct ethtool_link_ksettings *link_ksettings)
|
||||
{
|
||||
struct crete_vnic_priv *vnic_priv = netdev_priv(dev);
|
||||
|
||||
return crete_ethtool_set_link_ksettings(vnic_priv, link_ksettings);
|
||||
}
|
||||
|
||||
static void ptys2ethtool_adver_link(u32 eth_speed_cap,
|
||||
u8 tx_pause, u8 rx_pause, struct ethtool_link_ksettings *link_ksettings)
|
||||
{
|
||||
unsigned long speed_cap = eth_speed_cap;
|
||||
unsigned long *advertising_modes = link_ksettings->link_modes.advertising;
|
||||
int speed;
|
||||
|
||||
for_each_set_bit(speed, &speed_cap, CRETE_LINK_MODES_CAP_BIT)
|
||||
bitmap_or(advertising_modes, advertising_modes,
|
||||
ptys2ethtool_table[speed].advertised,
|
||||
__ETHTOOL_LINK_MODE_MASK_NBITS);
|
||||
if (rx_pause)
|
||||
ethtool_link_ksettings_add_link_mode(link_ksettings, advertising, Pause);
|
||||
if (tx_pause ^ rx_pause)
|
||||
ethtool_link_ksettings_add_link_mode(link_ksettings, advertising, Asym_Pause);
|
||||
}
|
||||
|
||||
static void ptys2ethtool_supported_link(u32 eth_speed_cap,
|
||||
struct ethtool_link_ksettings *link_ksettings)
|
||||
{
|
||||
unsigned long speed_cap = eth_speed_cap;
|
||||
unsigned long *supported_modes = link_ksettings->link_modes.supported;
|
||||
int speed;
|
||||
|
||||
for_each_set_bit(speed, &speed_cap, CRETE_LINK_MODES_CAP_BIT)
|
||||
bitmap_or(supported_modes, supported_modes,
|
||||
ptys2ethtool_table[speed].supported,
|
||||
__ETHTOOL_LINK_MODE_MASK_NBITS);
|
||||
ethtool_link_ksettings_add_link_mode(link_ksettings, supported, Pause);
|
||||
}
|
||||
|
||||
static int get_fec_supported_advertised(struct crete_core_dev *cdev,
|
||||
struct ethtool_link_ksettings *link_ksettings)
|
||||
{
|
||||
u16 active_fec;
|
||||
u16 eth_fec_cap;
|
||||
u8 fec;
|
||||
int err;
|
||||
unsigned long fec_cap;
|
||||
|
||||
err = crete_get_fec_mode(cdev, &active_fec, ð_fec_cap);
|
||||
if (err)
|
||||
return err;
|
||||
fec_cap = eth_fec_cap;
|
||||
for_each_set_bit(fec, &fec_cap, ARRAY_SIZE(crete_fec_2_ethtool_bit))
|
||||
__set_bit(crete_fec_2_ethtool_bit[fec], link_ksettings->link_modes.supported);
|
||||
|
||||
if (active_fec <= CRETE_FEC_LLRS)
|
||||
__set_bit(crete_fec_2_ethtool_bit[active_fec],
|
||||
link_ksettings->link_modes.advertising);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int crete_vnic_get_link_ksettings(struct net_device *dev,
|
||||
struct ethtool_link_ksettings *link_ksettings)
|
||||
{
|
||||
struct crete_speed_duplex sd = {0};
|
||||
struct crete_vnic_priv *vnic_priv = netdev_priv(dev);
|
||||
struct crete_core_dev *cdev = vnic_priv->coredev;
|
||||
u8 rx_pause = 0;
|
||||
u8 tx_pause = 0;
|
||||
int ret = 0;
|
||||
|
||||
link_ksettings->base.speed = SPEED_UNKNOWN;
|
||||
link_ksettings->base.duplex = DUPLEX_UNKNOWN;
|
||||
ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising);
|
||||
ethtool_link_ksettings_zero_link_mode(link_ksettings, supported);
|
||||
|
||||
crete_get_pfc_enable(cdev, &rx_pause, &tx_pause);
|
||||
|
||||
ret = crete_get_port_speed_duplex(cdev, &sd);
|
||||
if (ret) {
|
||||
netdev_err(dev, "Failed to get speed and duplex mode!\n");
|
||||
ret = 0;
|
||||
}
|
||||
if (sd.speed >= CRETE_10GBASE && sd.speed < CRETE_LINK_MODES_NUMBER)
|
||||
link_ksettings->base.speed = crete_link_speed[sd.speed];
|
||||
|
||||
if (sd.duplex >= CRETE_HALF_DUPLEX && sd.duplex < CRETE_DUPLEX_MAX)
|
||||
link_ksettings->base.duplex = crete_link_duplex[sd.duplex];
|
||||
|
||||
netdev_info(dev, "Speed Get speed[%d] speed_cap[0x%x].\n", sd.speed, sd.speed_cap);
|
||||
ptys2ethtool_supported_link(sd.speed_cap, link_ksettings);
|
||||
ptys2ethtool_adver_link(sd.speed_cap, tx_pause, rx_pause, link_ksettings);
|
||||
link_ksettings->base.port = PORT_FIBRE;
|
||||
|
||||
ret = get_fec_supported_advertised(cdev, link_ksettings);
|
||||
if (ret) {
|
||||
netdev_err(dev, "%s: FEC caps query failed: %d\n",
|
||||
__func__, ret);
|
||||
ret = 0; /* don't fail caps query because of FEC error */
|
||||
}
|
||||
|
||||
ethtool_link_ksettings_add_link_mode(link_ksettings, supported, FIBRE);
|
||||
ethtool_link_ksettings_add_link_mode(link_ksettings, advertising, FIBRE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int crete_vnic_set_fecparam(struct net_device *dev,
|
||||
struct ethtool_fecparam *fecparam)
|
||||
{
|
||||
struct crete_vnic_priv *vnic_priv = netdev_priv(dev);
|
||||
struct crete_core_dev *cdev = vnic_priv->coredev;
|
||||
|
||||
unsigned long fec_bitmap;
|
||||
u16 fec_policy = 0;
|
||||
|
||||
bitmap_from_arr32(&fec_bitmap, &fecparam->fec, sizeof(fecparam->fec) * BITS_PER_BYTE);
|
||||
if (bitmap_weight(&fec_bitmap, ETHTOOL_FEC_LLRS_BIT + 1) > 1)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
switch (fecparam->fec) {
|
||||
case ETHTOOL_FEC_OFF:
|
||||
fec_policy = CRETE_FEC_OFF;
|
||||
break;
|
||||
case ETHTOOL_FEC_RS:
|
||||
fec_policy = CRETE_FEC_RS;
|
||||
break;
|
||||
case ETHTOOL_FEC_BASER:
|
||||
fec_policy = CRETE_FEC_BASER;
|
||||
break;
|
||||
default:
|
||||
netdev_err(dev, "Unsupported FEC mode: %d\n", fecparam->fec);
|
||||
return -EINVAL;
|
||||
}
|
||||
return crete_set_fec_mode(cdev, fec_policy);
|
||||
}
|
||||
|
||||
static u32 crete_fec_cap_to_ethtool_fec(u16 fec_cap)
|
||||
{
|
||||
u32 ethtool_fec = 0;
|
||||
|
||||
if (fec_cap & BIT(CRETE_FEC_OFF))
|
||||
ethtool_fec |= ETHTOOL_FEC_OFF;
|
||||
|
||||
if (fec_cap & BIT(CRETE_FEC_AUTO))
|
||||
ethtool_fec |= ETHTOOL_FEC_AUTO;
|
||||
|
||||
if (fec_cap & BIT(CRETE_FEC_RS))
|
||||
ethtool_fec |= ETHTOOL_FEC_RS;
|
||||
|
||||
if (fec_cap & BIT(CRETE_FEC_BASER))
|
||||
ethtool_fec |= ETHTOOL_FEC_BASER;
|
||||
|
||||
if (fec_cap & BIT(CRETE_FEC_LLRS))
|
||||
ethtool_fec |= ETHTOOL_FEC_LLRS;
|
||||
|
||||
return ethtool_fec;
|
||||
}
|
||||
|
||||
static int crete_vnic_get_fecparam(struct net_device *dev,
|
||||
struct ethtool_fecparam *fecparam)
|
||||
{
|
||||
struct crete_vnic_priv *vnic_priv = netdev_priv(dev);
|
||||
struct crete_core_dev *cdev = vnic_priv->coredev;
|
||||
u16 fec_active;
|
||||
u16 fec_cap;
|
||||
int err;
|
||||
|
||||
err = crete_get_fec_mode(cdev, &fec_active, &fec_cap);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
fecparam->active_fec = crete_fec_2_ethtool[fec_active];
|
||||
|
||||
fecparam->fec = crete_fec_cap_to_ethtool_fec(fec_cap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ethtool_ops crete_vnic_ethtool_ops = {
|
||||
.get_drvinfo = crete_vnic_get_drvinfo,
|
||||
.get_link = crete_vnic_get_link,
|
||||
.get_ringparam = crete_vnic_get_ringparam,
|
||||
.get_strings = crete_vnic_get_strings,
|
||||
.get_sset_count = crete_vnic_get_sset_count,
|
||||
.get_ethtool_stats = crete_vnic_get_ethtool_stats,
|
||||
.get_channels = crete_vnic_get_channels,
|
||||
.set_channels = crete_vnic_set_channels,
|
||||
.flash_device = crete_vnic_flash_device,
|
||||
.get_link_ksettings = crete_vnic_get_link_ksettings,
|
||||
.set_link_ksettings = crete_vnic_set_link_ksettings,
|
||||
.get_fecparam = crete_vnic_get_fecparam,
|
||||
.set_fecparam = crete_vnic_set_fecparam,
|
||||
};
|
||||
|
||||
void crete_set_ethtool_ops(struct net_device *netdev)
|
||||
{
|
||||
netdev->ethtool_ops = &crete_vnic_ethtool_ops;
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _CRETE_NIC_ETHTOOL_H_
|
||||
#define _CRETE_NIC_ETHTOOL_H_
|
||||
void crete_set_ethtool_ops(struct net_device *netdev);
|
||||
void crete_build_ptys2ethtool_map(void);
|
||||
#endif /* _CRETE_NIC_ETHTOOL_H_*/
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,55 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _CRETE_NIC_IO_H_
|
||||
#define _CRETE_NIC_IO_H_
|
||||
void crete_set_netdev_ops(struct net_device *netdev);
|
||||
void crete_set_ethtool_ops(struct net_device *netdev);
|
||||
void free_unused_bufs(struct crete_vnic_priv *vnic_priv);
|
||||
void free_receive_bufs(struct crete_vnic_priv *vnic_priv);
|
||||
void free_receive_page_frags(struct crete_vnic_priv *vnic_priv);
|
||||
int crete_vnic_set_queues(struct net_device *netdev, u16 queue_pairs);
|
||||
int __crete_vnic_set_queues(struct net_device *netdev, u16 queue_pairs);
|
||||
void crete_vnic_recv_done(struct virtqueue *rvq);
|
||||
void crete_vnic_xmit_done(struct virtqueue *vq);
|
||||
int crete_vnic_poll_tx(struct napi_struct *napi, int budget);
|
||||
int crete_vnic_poll(struct napi_struct *napi, int budget);
|
||||
void crete_vnic_alloc_recv_buf(struct work_struct *work);
|
||||
void crete_vnic_get_strings(struct net_device *dev, u32 stringset, u8 *data);
|
||||
int crete_vnic_get_sset_count(struct net_device *dev, int sset);
|
||||
void crete_vnic_get_ethtool_stats(struct net_device *dev,
|
||||
struct ethtool_stats *stats, u64 *data);
|
||||
#endif /* _CRETE_NIC_IO_H_*/
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,166 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
# When the make command line has the goal 'all' or no goal specified (i.e.
|
||||
# when compiling the driver) a sub-make of the kernel's Makefile includes
|
||||
# the kernel configuration (include/config/auto.conf), but if any other
|
||||
# goal is specified (e.g. install) the kernel configuration does not get
|
||||
# included. Set a variable and export it to track over sub-makes.
|
||||
ifeq ($(MAKELEVEL),0)
|
||||
ifeq ($(filter-out all, $(MAKECMDGOALS)),)
|
||||
export KERNEL_CONFIG_INCLUDED=1
|
||||
endif
|
||||
endif
|
||||
|
||||
# Explicitly set shell to bash, to avoid issues on distros with a different
|
||||
# default shell. Looking at you, Ubuntu.
|
||||
SHELL=/bin/bash
|
||||
|
||||
COMMON_MK ?= $(wildcard $(src)/common.mk)
|
||||
ifeq (${COMMON_MK},)
|
||||
override src = .
|
||||
COMMON_MK = $(wildcard $(src)/common.mk)
|
||||
endif
|
||||
ifeq (${COMMON_MK},)
|
||||
$(error Cannot find common.mk build rules)
|
||||
else
|
||||
include ${COMMON_MK}
|
||||
endif
|
||||
|
||||
# SIOV support is only supported if the kernel has features for controlling
|
||||
# PASID support. Do not even try to build SIOV support if the kernel lacks
|
||||
# the necessary infrastructure.
|
||||
ifeq ($(call is_kcompat_defined,HAVE_PASID_SUPPORT),1)
|
||||
ifeq ($(call is_kcompat_defined,HAVE_IOMMU_DEV_FEAT_AUX),1)
|
||||
export ENABLE_SIOV_SUPPORT := 1
|
||||
endif
|
||||
endif
|
||||
|
||||
# LM support is only enabled if the kernel has features for LM v1 protocol.
|
||||
# If the kernel lacks the necessary infrastructure, LM support will be disabled.
|
||||
ifeq ($(call is_kcompat_defined,HAVE_LMV1_SUPPORT),1)
|
||||
export ENABLE_LM_SUPPORT := 1
|
||||
endif
|
||||
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
# kbuild part of makefile
|
||||
#
|
||||
ccflags-y += -I$(src)
|
||||
subdir-ccflags-y += -I$(src)
|
||||
|
||||
obj-m += crete_vdpa.o
|
||||
|
||||
crete_vdpa-y := crete_vdpa_main.o \
|
||||
crete_vdpa_dev.o \
|
||||
|
||||
|
||||
else # ifneq($(KERNELRELEASE),)
|
||||
# normal makefile
|
||||
|
||||
DRIVER := crete_vdpa
|
||||
EXTRA_CFLAGS += -std=gnu11
|
||||
|
||||
# ice does not support building on kernels older than 3.10.0
|
||||
$(call minimum_kver_check,3,10,0)
|
||||
|
||||
# Command to update initramfs or display a warning message
|
||||
ifeq (${cmd_initrd},)
|
||||
define cmd_initramfs
|
||||
@echo "Unable to update initramfs. You may need to do this manually."
|
||||
endef
|
||||
else
|
||||
define cmd_initramfs
|
||||
@echo "Updating initramfs..."
|
||||
$(call cmd_initrd)
|
||||
endef
|
||||
endif
|
||||
|
||||
all:
|
||||
+$(call kernelbuild,modules)
|
||||
#@gzip -c ../${DRIVER}.${MANSECTION} > ${DRIVER}.${MANSECTION}.gz
|
||||
ifneq ($(wildcard lttng),)
|
||||
$(MAKE) -C lttng
|
||||
endif
|
||||
|
||||
clean:
|
||||
+$(call kernelbuild,clean)
|
||||
@-rm -rf *.${MANSECTION}.gz *.ko
|
||||
ifneq ($(wildcard lttng),)
|
||||
$(MAKE) -C lttng clean
|
||||
endif
|
||||
|
||||
# Install kernel module files. This target is called by the RPM specfile when
|
||||
# generating binary RPMs, and is not expected to modify files outside of the
|
||||
# build root. Thus, it must not update initramfs, or run depmod.
|
||||
modules_install: all
|
||||
+$(call kernelbuild,modules_install)
|
||||
#$(MAKE) auxiliary_install
|
||||
|
||||
# Install kernel module files without auxiliary. This target is called by the
|
||||
# RPM specfile when generating binary RPMs, and is not expected to modify
|
||||
# files outside of the build root. Thus, it must not update initramfs, or run depmod.
|
||||
modules_install_no_aux:
|
||||
@+$(call kernelbuild,modules_install)
|
||||
|
||||
mandocs_install: all
|
||||
install -D -m 644 ${DRIVER}.${MANSECTION}.gz ${INSTALL_MOD_PATH}/${MANDIR}/man${MANSECTION}/${DRIVER}.${MANSECTION}.gz
|
||||
|
||||
# After installing all the files, perform necessary work to ensure the system
|
||||
# will use the new modules. This includes running depmod to update module
|
||||
# dependencies and updating the initramfs image in case the module is loaded
|
||||
# during early boot.
|
||||
install: modules_install
|
||||
$(call cmd_depmod)
|
||||
$(call cmd_initramfs)
|
||||
|
||||
# Remove installed module files. This target is called by the RPM specfile when
|
||||
# generating binary RPMs, and is not expected to modify files outside of the
|
||||
# build root. Thus, it must not update the initramfs image or run depmod.
|
||||
modules_uninstall:
|
||||
rm -f ${INSTALL_MOD_PATH}/lib/modules/${KVER}/${INSTALL_MOD_DIR}/${DRIVER}.ko
|
||||
#$(MAKE) auxiliary_uninstall
|
||||
|
||||
mandocs_uninstall:
|
||||
rm -f ${INSTALL_MOD_PATH}/${MANDIR}/man${MANSECTION}/${DRIVER}.${MANSECTION}.gz 2>/dev/null
|
||||
|
||||
# After uninstalling all the files, perform necessary work to restore the
|
||||
# system back to using the default kernel modules. This includes running depmod
|
||||
# to update module dependencies and updating the initramfs image.
|
||||
uninstall: modules_uninstall
|
||||
$(call cmd_depmod)
|
||||
$(call cmd_initramfs)
|
||||
|
||||
#auxiliary_info:
|
||||
# @../scripts/check_aux_bus --verbose --ksrc="${KSRC}" --build-kernel="${BUILD_KERNEL}"
|
||||
|
||||
#auxiliary_install:
|
||||
# ${auxiliary_post_install}
|
||||
|
||||
#auxiliary_uninstall:
|
||||
# ${auxiliary_post_uninstall}
|
||||
|
||||
#ifeq (${NEED_AUX_BUS},1)
|
||||
#all: auxiliary_info
|
||||
#endif
|
||||
|
||||
help:
|
||||
@echo 'Building external (out-of-tree) modules:'
|
||||
@echo ' all - default target, build the module(s) and manpage'
|
||||
@echo ' clean - remove generated files'
|
||||
@echo ' modules_install - install the module(s) only'
|
||||
@echo ' install - install the module(s) and manpage, and update initramfs'
|
||||
@echo ' modules_uninstall - uninstall the module(s) only'
|
||||
@echo ' uninstall - uninstall the module(s) and manpage, and update initramfs'
|
||||
@echo ''
|
||||
@echo 'Command-line options:'
|
||||
@echo ' KSRC=<path> - Path to kernel source (defaults to running kernel)'
|
||||
@echo ' LINUX_VERSION=<x.y.z> - Debug tool to force kernel LINUX_VERSION_CODE for'
|
||||
@echo ' external module(s). *** Use at your own risk! ***'
|
||||
@echo ' INSTALL_MOD_PATH=<path> - Prefix added to default module(s) installation path'
|
||||
@echo ' (/lib/modules/$$(KERNELRELEASE)/)'
|
||||
@echo ' INSTALL_MOD_DIR=<path> - Install module(s) in subdirectory other than default'
|
||||
@echo ' (.../updates/drivers/net/ethernet/jm/${DRIVER}/)'
|
||||
@echo ''
|
||||
|
||||
.PHONY: all clean modules_install install modules_uninstall uninstall help
|
||||
|
||||
endif # ifneq($(KERNELRELEASE),)
|
8
LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/build_anos.sh
Executable file
8
LingYaoSNIC/HW/kernel/kernel-crete-front-driver/crete-vnet/build_anos.sh
Executable file
@ -0,0 +1,8 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#!/bin/bash
|
||||
# common build rules useful for out-of-tree Linux driver builds
|
||||
#
|
||||
make clean
|
||||
|
||||
make EXTRA_CFLAGS="-DHAVE_VDPA_JMND_OPS"
|
||||
|
@ -0,0 +1,8 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#!/bin/bash
|
||||
# common build rules useful for out-of-tree Linux driver builds
|
||||
#
|
||||
make clean
|
||||
|
||||
make EXTRA_CFLAGS="-DHAVE_VDPA_EULER_OPS"
|
||||
|
@ -0,0 +1,454 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#
|
||||
# common Makefile rules useful for out-of-tree Linux driver builds
|
||||
#
|
||||
# Usage: include common.mk
|
||||
#
|
||||
# After including, you probably want to add a minimum_kver_check call
|
||||
#
|
||||
# Required Variables:
|
||||
# DRIVER
|
||||
# -- Set to the lowercase driver name
|
||||
|
||||
#####################
|
||||
# Helpful functions #
|
||||
#####################
|
||||
|
||||
SHELL := $(shell which bash)
|
||||
src ?= $(dir $(realpath $(lastword $(MAKEFILE_LIST))))
|
||||
readlink = $(shell readlink -f ${1})
|
||||
|
||||
# helper functions for converting kernel version to version codes
|
||||
get_kver = $(or $(word ${2},$(subst ., ,${1})),0)
|
||||
get_kvercode = $(shell [ "${1}" -ge 0 -a "${1}" -le 255 2>/dev/null ] && \
|
||||
[ "${2}" -ge 0 -a "${2}" -le 255 2>/dev/null ] && \
|
||||
[ "${3}" -ge 0 -a "${3}" -le 255 2>/dev/null ] && \
|
||||
printf %d $$(( ( ${1} << 16 ) + ( ${2} << 8 ) + ( ${3} ) )) )
|
||||
|
||||
################
|
||||
# depmod Macro #
|
||||
################
|
||||
|
||||
cmd_depmod = /sbin/depmod $(if ${SYSTEM_MAP_FILE},-e -F ${SYSTEM_MAP_FILE}) \
|
||||
$(if $(strip ${INSTALL_MOD_PATH}),-b ${INSTALL_MOD_PATH}) \
|
||||
-a ${KVER}
|
||||
|
||||
#####################
|
||||
# Environment tests #
|
||||
#####################
|
||||
|
||||
DRIVER_UPPERCASE := $(shell echo ${DRIVER} | tr "[:lower:]" "[:upper:]")
|
||||
|
||||
ifeq (,${BUILD_KERNEL})
|
||||
BUILD_KERNEL=$(shell uname -r)
|
||||
endif
|
||||
|
||||
# Kernel Search Path
|
||||
# All the places we look for kernel source
|
||||
KSP := /lib/modules/${BUILD_KERNEL}/source \
|
||||
/lib/modules/${BUILD_KERNEL}/build \
|
||||
/usr/src/linux-${BUILD_KERNEL} \
|
||||
/usr/src/linux-$(${BUILD_KERNEL} | sed 's/-.*//') \
|
||||
/usr/src/kernel-headers-${BUILD_KERNEL} \
|
||||
/usr/src/kernel-source-${BUILD_KERNEL} \
|
||||
/usr/src/linux-$(${BUILD_KERNEL} | sed 's/\([0-9]*\.[0-9]*\)\..*/\1/') \
|
||||
/usr/src/linux \
|
||||
/usr/src/kernels/${BUILD_KERNEL} \
|
||||
/usr/src/kernels
|
||||
|
||||
# prune the list down to only values that exist and have an include/linux
|
||||
# sub-directory. We can't use include/config because some older kernels don't
|
||||
# have this.
|
||||
test_dir = $(shell [ -e ${dir}/include/linux ] && echo ${dir})
|
||||
KSP := $(foreach dir, ${KSP}, ${test_dir})
|
||||
|
||||
# we will use this first valid entry in the search path
|
||||
ifeq (,${KSRC})
|
||||
KSRC := $(firstword ${KSP})
|
||||
endif
|
||||
|
||||
ifeq (,${KSRC})
|
||||
$(warning *** Kernel header files not in any of the expected locations.)
|
||||
$(warning *** Install the appropriate kernel development package, e.g.)
|
||||
$(error kernel-devel, for building kernel modules and try again)
|
||||
else
|
||||
ifeq (/lib/modules/${BUILD_KERNEL}/source, ${KSRC})
|
||||
KOBJ := /lib/modules/${BUILD_KERNEL}/build
|
||||
else
|
||||
KOBJ := ${KSRC}
|
||||
endif
|
||||
endif
|
||||
|
||||
SCRIPT_PATH := ${KSRC}/scripts
|
||||
info_signed_modules =
|
||||
|
||||
ifeq (,${SCRIPT_PATH})
|
||||
info_signed_modules += echo "*** Could not find sign-file script. Cannot sign driver." ;
|
||||
else
|
||||
SIGN_FILE_EXISTS := $(or $(and $(wildcard $(SCRIPT_PATH)/sign-file),1),)
|
||||
PRIV_KEY_EXISTS := $(or $(and $(wildcard jm-linux-key.key),1),)
|
||||
PUB_KEY_EXISTS := $(or $(and $(wildcard jm-linux-key.crt),1),)
|
||||
ifneq ($(and $(SIGN_FILE_EXISTS),$(PRIV_KEY_EXISTS),$(PUB_KEY_EXISTS)),)
|
||||
info_signed_modules += \
|
||||
echo "*** Is sign-file present: ${SIGN_FILE_EXISTS}" ; \
|
||||
echo "*** Is private key present: ${PRIV_KEY_EXISTS}" ; \
|
||||
echo "*** Is public key present: ${PUB_KEY_EXISTS}" ;
|
||||
info_signed_modules += echo "*** All files are present, signing driver." ;
|
||||
sign_driver = $(shell ${SCRIPT_PATH}/sign-file sha256 jm-linux-key.key \
|
||||
intel-linux-key.crt ${DRIVER}.ko)
|
||||
else
|
||||
info_signed_modules += echo "*** Files are missing, cannot sign driver." ;
|
||||
sign_driver =
|
||||
endif
|
||||
endif
|
||||
|
||||
# Version file Search Path
|
||||
VSP := ${KOBJ}/include/generated/utsrelease.h \
|
||||
${KOBJ}/include/linux/utsrelease.h \
|
||||
${KOBJ}/include/linux/version.h \
|
||||
${KOBJ}/include/generated/uapi/linux/version.h \
|
||||
/boot/vmlinuz.version.h
|
||||
|
||||
# Config file Search Path
|
||||
CSP := ${KOBJ}/include/generated/autoconf.h \
|
||||
${KOBJ}/include/linux/autoconf.h \
|
||||
/boot/vmlinuz.autoconf.h
|
||||
|
||||
# System.map Search Path (for depmod)
|
||||
MSP := ${KSRC}/System.map \
|
||||
/usr/lib/debug/boot/System.map-${BUILD_KERNEL} \
|
||||
/boot/System.map-${BUILD_KERNEL}
|
||||
|
||||
# prune the lists down to only files that exist
|
||||
test_file = $(shell [ -f ${1} ] && echo ${1})
|
||||
VSP := $(foreach file, ${VSP}, $(call test_file,${file}))
|
||||
CSP := $(foreach file, ${CSP}, $(call test_file,${file}))
|
||||
MSP := $(foreach file, ${MSP}, $(call test_file,${file}))
|
||||
|
||||
|
||||
# and use the first valid entry in the Search Paths
|
||||
ifeq (,${VERSION_FILE})
|
||||
VERSION_FILE := $(firstword ${VSP})
|
||||
endif
|
||||
|
||||
ifeq (,${CONFIG_FILE})
|
||||
CONFIG_FILE := $(firstword ${CSP})
|
||||
endif
|
||||
|
||||
ifeq (,${SYSTEM_MAP_FILE})
|
||||
SYSTEM_MAP_FILE := $(firstword ${MSP})
|
||||
endif
|
||||
|
||||
ifeq (,$(wildcard ${VERSION_FILE}))
|
||||
$(error Linux kernel source not configured - missing version header file)
|
||||
endif
|
||||
|
||||
ifeq (,$(wildcard ${CONFIG_FILE}))
|
||||
$(error Linux kernel source not configured - missing autoconf.h)
|
||||
endif
|
||||
|
||||
ifeq (,$(wildcard ${SYSTEM_MAP_FILE}))
|
||||
$(warning Missing System.map file - depmod will not check for missing symbols during module installation)
|
||||
endif
|
||||
|
||||
ifneq ($(words $(subst :, ,$(CURDIR))), 1)
|
||||
$(error Sources directory '$(CURDIR)' cannot contain spaces nor colons. Rename directory or move sources to another path)
|
||||
endif
|
||||
|
||||
########################
|
||||
# Extract config value #
|
||||
########################
|
||||
|
||||
get_config_value = $(shell ${CC} -E -dM ${CONFIG_FILE} 2> /dev/null |\
|
||||
grep -m 1 ${1} | awk '{ print $$3 }')
|
||||
|
||||
################
|
||||
# dracut Macro #
|
||||
################
|
||||
|
||||
cmd_initrd := $(shell \
|
||||
if [[ ${KOBJ} != /lib/modules/${BUILD_KERNEL}/* ]]; then \
|
||||
echo ""; \
|
||||
elif which dracut > /dev/null 2>&1 ; then \
|
||||
echo "dracut --force --kver ${BUILD_KERNEL}"; \
|
||||
elif which update-initramfs > /dev/null 2>&1 ; then \
|
||||
echo "update-initramfs -u -k ${BUILD_KERNEL}"; \
|
||||
fi )
|
||||
|
||||
########################
|
||||
# Check module signing #
|
||||
########################
|
||||
|
||||
CONFIG_MODULE_SIG_ALL := $(call get_config_value,CONFIG_MODULE_SIG_ALL)
|
||||
CONFIG_MODULE_SIG_FORCE := $(call get_config_value,CONFIG_MODULE_SIG_FORCE)
|
||||
CONFIG_MODULE_SIG_KEY := $(call get_config_value,CONFIG_MODULE_SIG_KEY)
|
||||
|
||||
SIG_KEY_SP := ${KOBJ}/${CONFIG_MODULE_SIG_KEY} \
|
||||
${KOBJ}/certs/signing_key.pem
|
||||
|
||||
SIG_KEY_FILE := $(firstword $(foreach file, ${SIG_KEY_SP}, $(call test_file,${file})))
|
||||
|
||||
# print a warning if the kernel configuration attempts to sign modules but
|
||||
# the signing key can't be found.
|
||||
ifneq (${SIG_KEY_FILE},)
|
||||
warn_signed_modules := : ;
|
||||
else
|
||||
warn_signed_modules :=
|
||||
ifeq (${CONFIG_MODULE_SIG_ALL},1)
|
||||
warn_signed_modules += \
|
||||
echo "*** The target kernel has CONFIG_MODULE_SIG_ALL enabled, but" ; \
|
||||
echo "*** the signing key cannot be found. Module signing has been" ; \
|
||||
echo "*** disabled for this build." ;
|
||||
endif # CONFIG_MODULE_SIG_ALL=y
|
||||
ifeq (${CONFIG_MODULE_SIG_FORCE},1)
|
||||
warn_signed_modules += \
|
||||
echo "warning: The target kernel has CONFIG_MODULE_SIG_FORCE enabled," ; \
|
||||
echo "warning: but the signing key cannot be found. The module must" ; \
|
||||
echo "warning: be signed manually using 'scripts/sign-file'." ;
|
||||
endif # CONFIG_MODULE_SIG_FORCE
|
||||
DISABLE_MODULE_SIGNING := Yes
|
||||
endif
|
||||
|
||||
#######################
|
||||
# Linux Version Setup #
|
||||
#######################
|
||||
|
||||
# The following command line parameter is intended for development of KCOMPAT
|
||||
# against upstream kernels such as net-next which have broken or non-updated
|
||||
# version codes in their Makefile. They are intended for debugging and
|
||||
# development purpose only so that we can easily test new KCOMPAT early. If you
|
||||
# don't know what this means, you do not need to set this flag. There is no
|
||||
# arcane magic here.
|
||||
|
||||
# Convert LINUX_VERSION into LINUX_VERSION_CODE
|
||||
ifneq (${LINUX_VERSION},)
|
||||
LINUX_VERSION_CODE=$(call get_kvercode,$(call get_kver,${LINUX_VERSION},1),$(call get_kver,${LINUX_VERSION},2),$(call get_kver,${LINUX_VERSION},3))
|
||||
endif
|
||||
|
||||
# Honor LINUX_VERSION_CODE
|
||||
ifneq (${LINUX_VERSION_CODE},)
|
||||
$(warning Forcing target kernel to build with LINUX_VERSION_CODE of ${LINUX_VERSION_CODE}$(if ${LINUX_VERSION}, from LINUX_VERSION=${LINUX_VERSION}). Do this at your own risk.)
|
||||
KVER_CODE := ${LINUX_VERSION_CODE}
|
||||
EXTRA_CFLAGS += -DLINUX_VERSION_CODE=${LINUX_VERSION_CODE}
|
||||
endif
|
||||
|
||||
# Determine SLE_KERNEL_REVISION for SuSE SLE >= 11 (needed by kcompat)
|
||||
# This assumes SuSE will continue setting CONFIG_LOCALVERSION to the string
|
||||
# appended to the stable kernel version on which their kernel is based with
|
||||
# additional versioning information (up to 3 numbers), a possible abbreviated
|
||||
# git SHA1 commit id and a kernel type, e.g. CONFIG_LOCALVERSION=-1.2.3-default
|
||||
# or CONFIG_LOCALVERSION=-999.gdeadbee-default
|
||||
# SLE >= 15SP3 added additional information about version and service pack
|
||||
# to their kernel version e.g CONFIG_LOCALVERSION=-150300.59.43.1-default
|
||||
#
|
||||
# SLE_LOCALVERSION_CODE is also exported to support legacy kcompat.h
|
||||
# definitions.
|
||||
ifeq (1,$(call get_config_value,CONFIG_SUSE_KERNEL))
|
||||
|
||||
ifneq (10,$(call get_config_value,CONFIG_SLE_VERSION))
|
||||
|
||||
CONFIG_LOCALVERSION := $(call get_config_value,CONFIG_LOCALVERSION)
|
||||
LOCALVERSION := $(shell echo ${CONFIG_LOCALVERSION} | \
|
||||
cut -d'-' -f2 | sed 's/\.g[[:xdigit:]]\{7\}//')
|
||||
LOCALVER_A := $(shell echo ${LOCALVERSION} | cut -d'.' -f1)
|
||||
ifeq ($(shell test ${LOCALVER_A} -gt 65535; echo $$?),0)
|
||||
LOCAL_VER_MAJOR := $(shell echo ${LOCALVER_A:0:3})
|
||||
LOCAL_VER_MINOR := $(shell echo ${LOCALVER_A:3:3})
|
||||
LOCALVER_B := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f2)
|
||||
LOCALVER_C := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f3)
|
||||
LOCALVER_D := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f4)
|
||||
SLE_LOCALVERSION_CODE := $(shell expr ${LOCALVER_B} \* 65536 + \
|
||||
0${LOCALVER_C} \* 256 + 0${LOCALVER_D})
|
||||
EXTRA_CFLAGS += -DSLE_LOCALVERSION_CODE=${SLE_LOCALVERSION_CODE}
|
||||
EXTRA_CFLAGS += -DSLE_KERNEL_REVISION=${LOCALVER_B}
|
||||
else
|
||||
LOCALVER_B := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f2)
|
||||
LOCALVER_C := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f3)
|
||||
SLE_LOCALVERSION_CODE := $(shell expr ${LOCALVER_A} \* 65536 + \
|
||||
0${LOCALVER_B} \* 256 + 0${LOCALVER_C})
|
||||
EXTRA_CFLAGS += -DSLE_LOCALVERSION_CODE=${SLE_LOCALVERSION_CODE}
|
||||
EXTRA_CFLAGS += -DSLE_KERNEL_REVISION=${LOCALVER_A}
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
EXTRA_CFLAGS += ${CFLAGS_EXTRA}
|
||||
|
||||
# get the kernel version - we use this to find the correct install path
|
||||
KVER := $(shell ${CC} ${EXTRA_CFLAGS} -E -dM ${VERSION_FILE} | grep UTS_RELEASE | \
|
||||
awk '{ print $$3 }' | sed 's/\"//g')
|
||||
|
||||
# assume source symlink is the same as build, otherwise adjust KOBJ
|
||||
ifneq (,$(wildcard /lib/modules/${KVER}/build))
|
||||
ifneq (${KSRC},$(call readlink,/lib/modules/${KVER}/build))
|
||||
KOBJ=/lib/modules/${KVER}/build
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq (${KVER_CODE},)
|
||||
KVER_CODE := $(shell ${CC} ${EXTRA_CFLAGS} -E -dM ${VSP} 2> /dev/null |\
|
||||
grep -m 1 LINUX_VERSION_CODE | awk '{ print $$3 }' | sed 's/\"//g')
|
||||
endif
|
||||
|
||||
# minimum_kver_check
|
||||
#
|
||||
# helper function to provide uniform output for different drivers to abort the
|
||||
# build based on kernel version check. Usage: "$(call minimum_kver_check,2,6,XX)".
|
||||
define _minimum_kver_check
|
||||
ifeq (0,$(shell [ ${KVER_CODE} -lt $(call get_kvercode,${1},${2},${3}) ]; echo "$$?"))
|
||||
$$(warning *** Aborting the build.)
|
||||
$$(error This driver is not supported on kernel versions older than ${1}.${2}.${3})
|
||||
endif
|
||||
endef
|
||||
minimum_kver_check = $(eval $(call _minimum_kver_check,${1},${2},${3}))
|
||||
|
||||
#############################
|
||||
# kcompat definitions setup #
|
||||
#############################
|
||||
|
||||
# In most cases, kcompat flags can be checked within the driver source files
|
||||
# using simple CPP checks. However, it may be necessary to check for a flag
|
||||
# value within the Makefile for some specific edge cases. For example, if an
|
||||
# entire feature ought to be excluded on some kernels due to missing
|
||||
# functionality.
|
||||
#
|
||||
# To support this, kcompat_defs.h is preprocessed and converted into a word list
|
||||
# that can be checked to determine whether a given kcompat feature flag will
|
||||
# be defined for this kernel.
|
||||
#
|
||||
# KCOMPAT_DEFINITIONS holds the set of all macros which are defined. Note
|
||||
# this does include a large number of standard/builtin definitions.
|
||||
#
|
||||
# Use is_kcompat_defined as a $(call) function to check whether a given flag
|
||||
# is defined or undefined. For example:
|
||||
#
|
||||
# ifeq ($(call is_kcompat_defined,HAVE_FEATURE_FLAG),1)
|
||||
#
|
||||
# ifneq ($(call is_kcompat_defined,HAVE_FEATURE_FLAG),1)
|
||||
#
|
||||
# The is_kcompat_defined function returns 1 if the macro name is defined,
|
||||
# and the empty string otherwise.
|
||||
#
|
||||
# There is no mechanism to extract the value of the kcompat definition.
|
||||
# Supporting this would be non-trivial as Make does not have a map variable
|
||||
# type.
|
||||
#
|
||||
# Note that only the new layout is supported. Legacy definitions in
|
||||
# kcompat.h are not supported. If you need to check one of these, please
|
||||
# refactor it into the new layout.
|
||||
|
||||
# call script that populates defines automatically
|
||||
#
|
||||
# since is_kcompat_defined() is a macro, it's "computed" before any target
|
||||
# recipe, kcompat_generated_defs.h is needed prior to that, so needs to be
|
||||
# generated also via $(shell) call, which makes error handling ugly
|
||||
$(if $(shell \
|
||||
$(if $(findstring 1,${V}),,QUIET_COMPAT=1) \
|
||||
KSRC=${KSRC} OUT=${src}/kcompat_generated_defs.h CONFFILE=${CONFIG_FILE} \
|
||||
bash ${src}/kcompat-generator.sh && echo ok), , $(error kcompat-generator.sh failed))
|
||||
|
||||
KCOMPAT_DEFINITIONS := $(shell ${CC} ${EXTRA_CFLAGS} -E -dM \
|
||||
-I${KOBJ}/include \
|
||||
-I${KOBJ}/include/generated/uapi \
|
||||
${src}/kcompat_defs.h | awk '{ print $$2 }')
|
||||
|
||||
is_kcompat_defined = $(if $(filter ${1},${KCOMPAT_DEFINITIONS}),1,)
|
||||
|
||||
################
|
||||
# Manual Pages #
|
||||
################
|
||||
|
||||
MANSECTION = 7
|
||||
|
||||
ifeq (,${MANDIR})
|
||||
# find the best place to install the man page
|
||||
MANPATH := $(shell (manpath 2>/dev/null || echo $MANPATH) | sed 's/:/ /g')
|
||||
ifneq (,${MANPATH})
|
||||
# test based on inclusion in MANPATH
|
||||
test_dir = $(findstring ${dir}, ${MANPATH})
|
||||
else
|
||||
# no MANPATH, test based on directory existence
|
||||
test_dir = $(shell [ -e ${dir} ] && echo ${dir})
|
||||
endif
|
||||
# our preferred install path
|
||||
# should /usr/local/man be in here ?
|
||||
MANDIR := /usr/share/man /usr/man
|
||||
MANDIR := $(foreach dir, ${MANDIR}, ${test_dir})
|
||||
MANDIR := $(firstword ${MANDIR})
|
||||
endif
|
||||
ifeq (,${MANDIR})
|
||||
# fallback to /usr/man
|
||||
MANDIR := /usr/man
|
||||
endif
|
||||
|
||||
####################
|
||||
# CCFLAGS variable #
|
||||
####################
|
||||
|
||||
# set correct CCFLAGS variable for kernels older than 2.6.24
|
||||
ifeq (0,$(shell [ ${KVER_CODE} -lt $(call get_kvercode,2,6,24) ]; echo $$?))
|
||||
CCFLAGS_VAR := EXTRA_CFLAGS
|
||||
else
|
||||
CCFLAGS_VAR := ccflags-y
|
||||
endif
|
||||
|
||||
#################
|
||||
# KBUILD_OUTPUT #
|
||||
#################
|
||||
|
||||
# Only set KBUILD_OUTPUT if the real paths of KOBJ and KSRC differ
|
||||
ifneq ($(call readlink,${KSRC}),$(call readlink,${KOBJ}))
|
||||
export KBUILD_OUTPUT ?= ${KOBJ}
|
||||
endif
|
||||
|
||||
############################
|
||||
# Module Install Directory #
|
||||
############################
|
||||
|
||||
# Default to using updates/drivers/net/ethernet/jm/ path, since depmod since
|
||||
# v3.1 defaults to checking updates folder first, and only checking kernels/
|
||||
# and extra afterwards. We use updates instead of kernel/* due to desire to
|
||||
# prevent over-writing built-in modules files.
|
||||
export INSTALL_MOD_DIR ?= updates/drivers/net/ethernet/jm/${DRIVER}
|
||||
|
||||
|
||||
######################
|
||||
# Kernel Build Macro #
|
||||
######################
|
||||
|
||||
# kernel build function
|
||||
# ${1} is the kernel build target
|
||||
# ${2} may contain any extra rules to pass directly to the sub-make process
|
||||
#
|
||||
# This function is expected to be executed by
|
||||
# @+$(call kernelbuild,<target>,<extra parameters>)
|
||||
# from within a Makefile recipe.
|
||||
#
|
||||
# The following variables are expected to be defined for its use:
|
||||
# GCC_I_SYS -- if set it will enable use of gcc-i-sys.sh wrapper to use -isystem
|
||||
# CCFLAGS_VAR -- the CCFLAGS variable to set extra CFLAGS
|
||||
# EXTRA_CFLAGS -- a set of extra CFLAGS to pass into the ccflags-y variable
|
||||
# KSRC -- the location of the kernel source tree to build against
|
||||
# DRIVER_UPPERCASE -- the uppercase name of the kernel module, set from DRIVER
|
||||
# W -- if set, enables the W= kernel warnings options
|
||||
# C -- if set, enables the C= kernel sparse build options
|
||||
#
|
||||
#
|
||||
|
||||
KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/jm_auxiliary.symvers
|
||||
KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/crete.symvers
|
||||
KBUILD_EXTRA_SYMBOLS += /lib/modules/$(shell uname -r)/extern-symvers/vdpa.symvers
|
||||
#export KBUILD_EXTRA_SYMBOLS
|
||||
|
||||
kernelbuild = $(call warn_signed_modules) \
|
||||
${MAKE} $(if ${GCC_I_SYS},CC="${GCC_I_SYS}") \
|
||||
${CCFLAGS_VAR}="${EXTRA_CFLAGS}" \
|
||||
-C "${KSRC}" \
|
||||
CONFIG_${DRIVER_UPPERCASE}=m \
|
||||
$(if ${DISABLE_MODULE_SIGNING},CONFIG_MODULE_SIG=n) \
|
||||
$(if ${DISABLE_MODULE_SIGNING},CONFIG_MODULE_SIG_ALL=) \
|
||||
M="${CURDIR}" \
|
||||
$(if ${W},W="${W}") \
|
||||
$(if ${C},C="${C}") \
|
||||
${2} ${1}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,249 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* JaguarMicro virt device driver for virtio dataplane offloading
|
||||
*
|
||||
* Copyright (C) 2020 JaguarMicro Corporation.
|
||||
*
|
||||
* Author: Angus Chen <angus.chen@jaguarmicro.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _CRETE_VDPA_DEV_H_
|
||||
#define _CRETE_VDPA_DEV_H_
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pci_regs.h>
|
||||
#include <linux/vdpa.h>
|
||||
#include <uapi/linux/virtio_net.h>
|
||||
#include <uapi/linux/virtio_blk.h>
|
||||
#include <uapi/linux/virtio_config.h>
|
||||
#include <uapi/linux/virtio_pci.h>
|
||||
#include <linux/auxiliary_bus.h>
|
||||
#include "../crete-core/crete_cmd.h"
|
||||
#include "kcompat_generated_defs.h"
|
||||
/* Max 8 data queue pairs(16 queues) and one control vq for now. */
|
||||
#define CORSICA_MAX_QUEUES 65
|
||||
#define CORSICA_MAX_QUEUES_NOCTRL 64
|
||||
|
||||
#define CORSICA_QUEUE_ALIGNMENT PAGE_SIZE
|
||||
/*attention pls ,it's the depth of queue*/
|
||||
#define CORSICA_QUEUE_SIZE_MAX 1024
|
||||
#define CORSICA_QUEUE_SIZE_MIN 64
|
||||
#define CORSICA_MSI_CONFIG_OFF 0
|
||||
#define CORSICA_MSI_QUEUE_OFF 1
|
||||
#define CORSICA_PCI_MAX_RESOURCE 6
|
||||
#define VHOST_F_LOG_ALL 26
|
||||
#define VHOST_ACCESS_WO 0x2
|
||||
#define DEBUG
|
||||
|
||||
|
||||
|
||||
#define CORSICA_ERR(pdev, fmt, ...) dev_err(&pdev->dev, fmt, ##__VA_ARGS__)
|
||||
#define CORSICA_DBG(pdev, fmt, ...) dev_dbg(&pdev->dev, fmt, ##__VA_ARGS__)
|
||||
#define CORSICA_INFO(pdev, fmt, ...) dev_info(&pdev->dev, fmt, ##__VA_ARGS__)
|
||||
|
||||
#define CORSICA_DEV_CONFIG_OFFSIZE 0x40
|
||||
#define CORSICA_LOG_BASE_L 0x2
|
||||
#define CORSICA_LOG_BASE_H 0x6
|
||||
#define CORSICA_32_BIT_MASK 0xffffffff
|
||||
#define CORSICA_LOG_BASE 0x100000000000
|
||||
#define CORSICA_LM_DISABLE 0x0
|
||||
#define CORSICA_LM_ENABLE 0x1
|
||||
#define CORSICA_LM_STOP_DEV 0x2
|
||||
#define CORSICA_LM_ENABLE_VF 0x4
|
||||
#define CORSICA_LM_ENABLE_PF 0x8
|
||||
#define CORSICA_DEV_STOPED 0x4
|
||||
|
||||
#define VIRTIO_NET_CONFIG_OFFSET_MAC offsetof(struct virtio_net_config, mac)
|
||||
#define VIRTIO_NET_CONFIG_OFFSET_MTU offsetof(struct virtio_net_config, mtu)
|
||||
#define VIRTIO_NET_CONFIG_OFFSET_STATUS offsetof(struct virtio_net_config, status)
|
||||
#define CONFIG_ENABLE_TLP 0
|
||||
|
||||
#define CRETE_LOG_BASE_IOVA 0x100000000000
|
||||
/*************************support bclinux********************************/
|
||||
|
||||
#ifndef HAVE_VDPA_MGMTDEV_OPS
|
||||
struct vdpa_dev_set_config {
|
||||
struct {
|
||||
u8 mac[ETH_ALEN];
|
||||
u16 mtu;
|
||||
u16 max_vq_pairs;
|
||||
} net;
|
||||
u64 mask;
|
||||
};
|
||||
|
||||
struct vdpa_mgmtdev_ops;
|
||||
|
||||
struct vdpa_mgmt_dev {
|
||||
struct device *device;
|
||||
const struct vdpa_mgmtdev_ops *ops;
|
||||
struct virtio_device_id *id_table;
|
||||
u64 config_attr_mask;
|
||||
struct list_head list;
|
||||
u64 supported_features;
|
||||
u32 max_supported_vqs;
|
||||
};
|
||||
|
||||
|
||||
struct vdpa_mgmtdev_ops {
|
||||
int (*dev_add)(struct vdpa_mgmt_dev *mdev, const char *name,
|
||||
const struct vdpa_dev_set_config *config);
|
||||
void (*dev_del)(struct vdpa_mgmt_dev *mdev, struct vdpa_device *dev);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
enum crete_net_status {
|
||||
CRETE_NET_DEV_STARTUP,
|
||||
CRETE_NET_DEV_FEATURE_OK,
|
||||
CRETE_NET_DEV_DEV_OK,
|
||||
CRETE_NET_DEV_STOPPED
|
||||
};
|
||||
|
||||
#define CRETE_RX_SEQ 0
|
||||
#define CRETE_TX_SEQ 1
|
||||
|
||||
struct crete_mig_log {
|
||||
u32 log_base_l;
|
||||
u32 log_base_h;
|
||||
/* TODO: need use array to store multiple iova */
|
||||
u32 iova_addr_l;
|
||||
u32 iova_addr_h;
|
||||
u32 iova_size_l;
|
||||
u32 iova_size_h;
|
||||
struct list_head list;
|
||||
unsigned int limit;
|
||||
unsigned int nmaps;
|
||||
} __packed;
|
||||
|
||||
struct virtio_vdpa_config {
|
||||
union {
|
||||
struct virtio_net_config v_net_config;
|
||||
struct virtio_blk_config v_blk_config;
|
||||
u8 config_offset[CORSICA_DEV_CONFIG_OFFSIZE];
|
||||
};
|
||||
};
|
||||
|
||||
struct crete_vdpa_config {
|
||||
struct virtio_vdpa_config vdpa_config;
|
||||
u16 lm_ctrl;
|
||||
u16 reserved;
|
||||
u32 log_base_l;
|
||||
u32 log_base_h;
|
||||
struct crete_mig_log mig_log;
|
||||
u8 log_mask;
|
||||
u8 reserved1;
|
||||
} __packed;
|
||||
|
||||
struct crete_vring_lm_cfg {
|
||||
u16 last_avail_idx;
|
||||
u16 can_used; /* indircat the `last_avail_idx already been getted */
|
||||
};
|
||||
|
||||
struct crete_lm_cfg {
|
||||
struct crete_vdpa_config vdpa_lm_cfg;
|
||||
struct crete_vring_lm_cfg vring_lm_cfg[CORSICA_MAX_QUEUES];
|
||||
};
|
||||
|
||||
#define crete_private_to_vd(adapter) \
|
||||
(&((struct crete_adapter *)adapter)->vd)
|
||||
|
||||
struct vring_info {
|
||||
u64 desc;
|
||||
u64 avail;
|
||||
u64 used;
|
||||
u16 size;
|
||||
u16 last_avail_idx;
|
||||
bool ready;
|
||||
void __iomem *notify_addr;
|
||||
phys_addr_t notify_pa;
|
||||
u32 irq;
|
||||
u32 irqvec;
|
||||
struct vdpa_callback cb;
|
||||
char msix_name[256];
|
||||
};
|
||||
|
||||
struct crete_iotlb_map {
|
||||
struct list_head link;
|
||||
u64 start;
|
||||
u64 last;
|
||||
u64 size;
|
||||
u64 addr;
|
||||
u32 perm;
|
||||
u32 flags_padding;
|
||||
u64 __subtree_last;
|
||||
void *opaque;
|
||||
};
|
||||
|
||||
struct crete_vdpa {
|
||||
struct crete_vnet_hw_cap *hcap; //vdpa device hw capability
|
||||
/*********vdpa* soft capability*******/
|
||||
u8 status;
|
||||
u32 generation;
|
||||
u16 qp_nums;
|
||||
u16 num_queues;
|
||||
u16 queue_size;
|
||||
u64 driver_features;
|
||||
u32 dev_type;
|
||||
/************vdap queue***************************/
|
||||
struct vring_info vring[CORSICA_MAX_QUEUES];
|
||||
char config_msix_name[256];
|
||||
struct vdpa_callback config_cb;
|
||||
unsigned int config_irq;
|
||||
u32 config_size;
|
||||
u16 lm_ctrl;
|
||||
u16 announce_count;
|
||||
struct crete_mig_log mig_log;
|
||||
bool have_hw_ctrl;
|
||||
bool have_soft_ctrl;
|
||||
bool have_ctrl_irq;
|
||||
bool host_polling;
|
||||
__le16 ctl_qlen;
|
||||
u8 __iomem *lm_cfg;
|
||||
struct crete_vring_lm_cfg vring_lm_cfg[CORSICA_MAX_QUEUES];
|
||||
struct crete_nb cnb;
|
||||
spinlock_t iommu_lock;
|
||||
struct iommu_domain *domain;
|
||||
struct vhost_iotlb resv_iotlb;
|
||||
struct mm_struct *mm;
|
||||
};
|
||||
|
||||
|
||||
struct crete_adapter {
|
||||
struct vdpa_device vdpa;
|
||||
struct virtio_net_config config;
|
||||
struct crete_core_dev *cdev;
|
||||
struct crete_vdpa vd;
|
||||
struct crete_vdpa_mgmtdev *priv;
|
||||
};
|
||||
|
||||
struct crete_vnet_hw_cap {
|
||||
__le64 hw_features;
|
||||
__le16 max_vqpnum;
|
||||
__le16 io_qlen;
|
||||
__le16 ctl_qlen;
|
||||
bool have_ctl;
|
||||
__le16 vdpa_max_vqs;
|
||||
};
|
||||
|
||||
struct crete_vdpa_mgmtdev {
|
||||
struct vdpa_mgmt_dev mdev;
|
||||
struct crete_adapter *adapter;
|
||||
struct crete_core_dev *cdev;
|
||||
struct crete_vnet_hw_cap hcap;
|
||||
};
|
||||
|
||||
int crete_vdpa_set_hwstatus(struct crete_core_dev *core_dev, u8 status,
|
||||
struct device *dev);
|
||||
int crete_vdpa_get_mgmt_info(struct crete_vdpa_mgmtdev *cvm);
|
||||
|
||||
int crete_vdpa_dev_add(struct vdpa_mgmt_dev *mdev, const char *name,
|
||||
const struct vdpa_dev_set_config *config);
|
||||
|
||||
void crete_vdpa_dev_del(struct vdpa_mgmt_dev *mdev, struct vdpa_device *dev);
|
||||
int crete_vdpa_set_device_type(struct crete_core_dev *core_dev);
|
||||
#endif /* _CRETE_VDPA_DEV_H_ */
|
||||
|
||||
|
||||
|
@ -0,0 +1,171 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2023, Jaguar Micro. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/vdpa.h>
|
||||
#include "crete_vdpa_dev.h"
|
||||
#define CRETE_VDPA_DRV_DESCRIPTION "JaguarMicro/CRETE VDPA VF Device Driver"
|
||||
#define CRETE_VDPA_AUX_DEV_NAME "crete_core.vnet"
|
||||
#define CRETE_VDPA_DRV_NAME "crete_vnet"
|
||||
|
||||
static int crete_vdpa_probe(struct auxiliary_device *adev,
|
||||
const struct auxiliary_device_id *id)
|
||||
{
|
||||
struct crete_aux_dev *cadev =
|
||||
container_of(adev, struct crete_aux_dev, adev);
|
||||
struct crete_core_dev *core_dev = cadev->core_dev;
|
||||
struct pci_dev *pdev = core_dev->pdev;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct crete_vdpa_mgmtdev *cvm;
|
||||
int ret;
|
||||
#if defined(HAVE_VDPA_MGMTDEV_OPS)
|
||||
#else
|
||||
struct vdpa_dev_set_config vdsc;
|
||||
#endif
|
||||
|
||||
ret = crete_vdpa_set_device_type(core_dev);
|
||||
if (ret) {
|
||||
dev_err(dev,
|
||||
"Failed to alloc memory for the vDPA management device\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = crete_vdpa_set_hwstatus(core_dev, CRETE_NET_DEV_STARTUP, dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "set net dev status failed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
cvm = kzalloc(sizeof(struct crete_vdpa_mgmtdev), GFP_KERNEL);
|
||||
if (!cvm)
|
||||
return -ENOMEM;
|
||||
cvm->cdev = core_dev;
|
||||
ret = crete_vdpa_get_mgmt_info(cvm);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to set vDPA management\n");
|
||||
goto err;
|
||||
}
|
||||
dev_set_drvdata(&adev->dev, cvm);
|
||||
|
||||
#if defined(HAVE_VDPA_MGMTDEV_OPS)
|
||||
ret = vdpa_mgmtdev_register(&cvm->mdev);
|
||||
if (ret) {
|
||||
dev_err(dev,
|
||||
"Failed to initialize the management interfaces\n");
|
||||
goto err;
|
||||
}
|
||||
#else
|
||||
memset(&vdsc, 0, sizeof(struct vdpa_dev_set_config));
|
||||
ret = crete_vdpa_dev_add(&cvm->mdev, "NULL", &vdsc);
|
||||
if (ret) {
|
||||
dev_err(dev,
|
||||
"Failed to add vdpa device ret:%d\n",ret);
|
||||
goto err_add;
|
||||
}
|
||||
#endif
|
||||
|
||||
//crete_vdpa_debugfs_add_dev(cvm);
|
||||
//crete_vdpa_debugfs_add_hcap(cvm);
|
||||
return 0;
|
||||
err_add:
|
||||
dev_set_drvdata(&adev->dev, NULL);
|
||||
err:
|
||||
kfree(cvm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void crete_vdpa_remove(struct auxiliary_device *adev)
|
||||
{
|
||||
struct crete_vdpa_mgmtdev *crete_mgmt_dev;
|
||||
struct device *dev = &adev->dev;
|
||||
struct crete_adapter *adapter;
|
||||
struct vdpa_device *vdpa_dev;
|
||||
|
||||
crete_mgmt_dev = dev_get_drvdata(&adev->dev);
|
||||
|
||||
dev_info(dev, "crete vdpa remove\n");
|
||||
#if defined(HAVE_VDPA_MGMTDEV_OPS)
|
||||
vdpa_mgmtdev_unregister(&crete_mgmt_dev->mdev);
|
||||
#else
|
||||
adapter = crete_mgmt_dev->adapter;
|
||||
vdpa_dev = &adapter->vdpa;
|
||||
crete_vdpa_dev_del(&crete_mgmt_dev->mdev, vdpa_dev);
|
||||
crete_mgmt_dev->adapter = NULL;
|
||||
// crete_vdpa_debugfs_del_vdpadev(crete_mgmt_dev);
|
||||
kfree(crete_mgmt_dev);
|
||||
dev_set_drvdata(&adev->dev, NULL);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static const struct auxiliary_device_id crete_vdpa_id_table[] = {
|
||||
{.name = CRETE_VDPA_AUX_DEV_NAME,},
|
||||
{},
|
||||
};
|
||||
|
||||
static struct auxiliary_driver crete_vdpa_driver = {
|
||||
.name = CRETE_VDPA_DRV_NAME,
|
||||
.probe = crete_vdpa_probe,
|
||||
.remove = crete_vdpa_remove,
|
||||
.id_table = crete_vdpa_id_table,
|
||||
};
|
||||
|
||||
static void __exit crete_vdpa_cleanup(void)
|
||||
{
|
||||
auxiliary_driver_unregister(&crete_vdpa_driver);
|
||||
|
||||
// crete_vnet_debugfs_destroy();
|
||||
}
|
||||
|
||||
module_exit(crete_vdpa_cleanup);
|
||||
|
||||
static int __init crete_vdpa_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
// crete_vnet_debugfs_create();
|
||||
err = auxiliary_driver_register(&crete_vdpa_driver);
|
||||
if (err) {
|
||||
pr_err("%s: aux driver register failed: %pe\n",
|
||||
CRETE_VDPA_DRV_NAME, ERR_PTR(err));
|
||||
//crete_vnet_debugfs_destroy();
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
module_init(crete_vdpa_init);
|
||||
|
||||
MODULE_DESCRIPTION(CRETE_VDPA_DRV_DESCRIPTION);
|
||||
MODULE_AUTHOR("jaguarmicro.com");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION("3.1.1");
|
@ -0,0 +1,173 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
set -Eeuo pipefail
|
||||
|
||||
# This file generates HAVE_ and NEED_ defines for current kernel
|
||||
# (or KSRC if provided).
|
||||
#
|
||||
# It does so by 'gen' function calls (see body of 'gen-devlink' for examples).
|
||||
# 'gen' could look for various kinds of declarations in provided kernel headers,
|
||||
# eg look for an enum in one of files specified and check if given enumeration
|
||||
# (single value) is present. See 'Documentation' or comment above the 'gen' fun
|
||||
# in the kcompat-lib.sh.
|
||||
|
||||
# Why using bash/awk instead of an old/legacy approach?
|
||||
#
|
||||
# The aim is to replicate all the defines provided by human developers
|
||||
# in the past. Additional bonus is the fact, that we no longer need to care
|
||||
# about backports done by OS vendors (RHEL, SLES, ORACLE, UBUNTU, more to come).
|
||||
# We will even work (compile) with only part of backports provided.
|
||||
#
|
||||
# To enable smooth transition, especially in time of late fixes, "old" method
|
||||
# of providing flags should still work as usual.
|
||||
|
||||
# End of intro.
|
||||
# Find info about coding style/rules at the end of file.
|
||||
# Most of the implementation is in kcompat-lib.sh, here are actual 'gen' calls.
|
||||
|
||||
export LC_ALL=C
|
||||
SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")"
|
||||
ORIG_CWD="$(pwd)"
|
||||
trap 'rc=$?; echo >&2 "$(realpath "$ORIG_CWD/${BASH_SOURCE[0]}"):$LINENO: failed with rc: $rc"' ERR
|
||||
|
||||
# shellcheck source=kcompat-lib.sh
|
||||
source "$SCRIPT_DIR"/kcompat-lib.sh
|
||||
|
||||
# DO NOT break gen calls below (via \), to make our compat code more grep-able,
|
||||
# keep them also grouped, first by feature (like DEVLINK), then by .h filename
|
||||
# finally, keep them sorted within a group (sort by flag name)
|
||||
|
||||
# handy line of DOC copy-pasted form kcompat-lib.sh:
|
||||
# gen DEFINE if (KIND [METHOD of]) NAME [(matches|lacks) PATTERN|absent] in <list-of-files>
|
||||
|
||||
|
||||
function gen-vdpa() {
|
||||
vh='include/linux/vdpa.h'
|
||||
vm='include/linux/virtio_pci_modern.h'
|
||||
if [ -f $vm ];then
|
||||
gen HAVE_VIRTIO_PCI_MODERN if struct virtio_pci_modern_device in $vm
|
||||
fi
|
||||
#gen HAVE_VDPA_OPS_RESET_INFO if method reset of vdpa_config_ops matches lacks status in "$vh"
|
||||
gen HAVE_VDPA_RESET_LACK_INFO if method reset of vdpa_config_ops lacks state in "$vh"
|
||||
gen HAVE_VDPA_OPS_RESET if method reset of vdpa_config_ops in "$vh"
|
||||
gen HAVE_VDPA_ALLOC_LACK_GROUP if fun __vdpa_alloc_device lacks ngroups in "$vh"
|
||||
gen HAVE_VDPA_ALLOC_LACK_NAME if fun __vdpa_alloc_device lacks name in "$vh"
|
||||
gen HAVE_VDPA_VQ_STATE_LACK_PACKED if struct vdpa_vq_state lacks packed in "$vh"
|
||||
gen HAVE_VDPA_MGMTDEV_OPS if struct vdpa_mgmtdev_ops in "$vh"
|
||||
gen HAVE_VDPA_DEV_SET_CONFIG if struct vdpa_dev_set_config in "$vh"
|
||||
gen HAVE_VDPA_OPS_DEVICE_FEAT if method get_device_features of vdpa_config_ops in "$vh"
|
||||
gen HAVE_VDPA_OPS_GET_CONFIG_SIZE if method get_config_size of vdpa_config_ops in "$vh"
|
||||
gen HAVE_VDPA_OPS_LOG_BASE if method set_log_base of vdpa_config_ops in "$vh"
|
||||
gen HAVE_VDPA_OPS_NUM_MIN if method get_vq_num_min of vdpa_config_ops in "$vh"
|
||||
}
|
||||
|
||||
function gen-aux() {
|
||||
ah='include/linux/auxiliary_bus.h'
|
||||
mh='include/linux/mod_devicetable.h'
|
||||
if config_has CONFIG_AUXILIARY_BUS; then
|
||||
gen HAVE_AUXILIARY_DRIVER_INT_REMOVE if method remove of auxiliary_driver matches 'int' in "$ah"
|
||||
fi
|
||||
|
||||
# generate HAVE_AUXILIARY_DEVICE_ID only for cases when it's disabled in .config
|
||||
if ! config_has CONFIG_AUXILIARY_BUS; then
|
||||
gen HAVE_AUXILIARY_DEVICE_ID if struct auxiliary_device_id in "$mh"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
function gen-pci() {
|
||||
pcih='include/linux/pci.h'
|
||||
gen HAVE_PCI_MSIX_ALLOC_IRQ_AT if fun pci_msix_alloc_irq_at in "$pcih"
|
||||
gen HAVE_PCI_MSIX_CAN_ALLOC_DYN if fun pci_msix_can_alloc_dyn in "$pcih"
|
||||
gen HAVE_PCI_MSIX_FREE_IRQ if fun pci_msix_free_irq in "$pcih"
|
||||
gen HAVE_PER_VF_MSIX_SYSFS if method sriov_set_msix_vec_count of pci_driver in "$pcih"
|
||||
gen HAVE_STRUCT_PCI_DEV_PTM_ENABLED if struct pci_dev matches ptm_enabled in "$pcih"
|
||||
gen NEED_PCIE_FLR if fun pcie_flr absent in "$pcih"
|
||||
gen NEED_PCIE_FLR_RETVAL if fun pcie_flr lacks 'int pcie_flr' in "$pcih"
|
||||
gen NEED_PCIE_PTM_ENABLED if fun pcie_ptm_enabled absent in "$pcih"
|
||||
gen NEED_PCI_ENABLE_PTM if fun pci_enable_ptm absent in "$pcih"
|
||||
}
|
||||
|
||||
|
||||
# all the generations, extracted from main() to keep normal code and various
|
||||
# prep separated
|
||||
function gen-all() {
|
||||
# code above is covered by unit_tests/test_gold.sh
|
||||
if [ -n "${JUST_UNIT_TESTING-}" ]; then
|
||||
return
|
||||
fi
|
||||
gen-aux
|
||||
gen-vdpa
|
||||
gen-pci
|
||||
}
|
||||
|
||||
function main() {
|
||||
# check if caller (like our makefile) wants to redirect output to file
|
||||
if [ -n "${OUT-}" ]; then
|
||||
|
||||
# in case OUT exists, we don't want to overwrite it, instead
|
||||
# write to a temporary copy.
|
||||
if [ -s "${OUT}" ]; then
|
||||
TMP_OUT="$(mktemp "${OUT}.XXX")"
|
||||
trap "rm -f '${TMP_OUT}'" EXIT
|
||||
|
||||
REAL_OUT="${OUT}"
|
||||
OUT="${TMP_OUT}"
|
||||
fi
|
||||
|
||||
exec > "$OUT"
|
||||
# all stdout goes to OUT since now
|
||||
echo "/* Autogenerated for KSRC=${KSRC-} via $(basename "$0") */"
|
||||
fi
|
||||
if [ -d "${KSRC-}" ]; then
|
||||
cd "${KSRC}"
|
||||
fi
|
||||
|
||||
# check if KSRC was ok/if we are in proper place to look for headers
|
||||
if [ -z "$(filter-out-bad-files include/linux/kernel.h)" ]; then
|
||||
echo >&2 "seems that there are no kernel includes placed in KSRC=${KSRC}
|
||||
pwd=$(pwd); ls -l:"
|
||||
ls -l >&2
|
||||
exit 8
|
||||
fi
|
||||
|
||||
# we need some flags from .config or (autoconf.h), required
|
||||
if [ ! -f "${CONFFILE-}" ]; then
|
||||
echo >&2 ".config should be passed as env CONFFILE
|
||||
(and it's not set or not a file)"
|
||||
exit 9
|
||||
fi
|
||||
|
||||
echo "#ifndef _KCOMPAT_GENERATED_DEFS_H_"
|
||||
echo "#define _KCOMPAT_GENERATED_DEFS_H_"
|
||||
gen-all
|
||||
echo "#endif /* _KCOMPAT_GENERATED_DEFS_H_ */"
|
||||
|
||||
if [ -n "${OUT-}" ]; then
|
||||
cd "$ORIG_CWD"
|
||||
|
||||
# Compare and see if anything changed. This avoids updating
|
||||
# mtime of the file.
|
||||
if [ -n "${REAL_OUT-}" ]; then
|
||||
if cmp --silent "${REAL_OUT}" "${TMP_OUT}"; then
|
||||
# exit now, skipping print of the output since
|
||||
# there were no changes. the trap should
|
||||
# cleanup TMP_OUT
|
||||
exit 0
|
||||
fi
|
||||
|
||||
mv -f "${TMP_OUT}" "${REAL_OUT}"
|
||||
OUT="${REAL_OUT}"
|
||||
fi
|
||||
|
||||
# dump output, will be visible in CI
|
||||
if [ -n "${JUST_UNIT_TESTING-}${QUIET_COMPAT-}" ]; then
|
||||
return
|
||||
fi
|
||||
cat -n "$OUT" >&2
|
||||
fi
|
||||
}
|
||||
|
||||
main
|
||||
|
@ -0,0 +1,310 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
# to be sourced
|
||||
|
||||
# General shell helpers
|
||||
|
||||
# exit with non-zero exit code; if there is only one param:
|
||||
# exit with msg $1 and exit code from last command (or 99 if = 0)
|
||||
# otherwise, exit with $1 and use remaining arguments as msg
|
||||
function die() {
|
||||
rc=$?
|
||||
if [ $# -gt 1 ]; then
|
||||
rc="$1"
|
||||
shift
|
||||
fi
|
||||
[ "$rc" -ne 0 ] || rc=99
|
||||
echo >&2 "$@"
|
||||
exit $rc
|
||||
}
|
||||
|
||||
# filter out paths that are not files
|
||||
# input $@, output via echo;
|
||||
# note: pass `-` for stdin
|
||||
# note: outputs nothing if all input files are "bad" (eg. not existing), but it
|
||||
# is left for caller to decide if this is an erorr condition;
|
||||
# note: whitespaces are considered "bad" as part of filename, it's an error.
|
||||
function filter-out-bad-files() {
|
||||
if [[ $# = 1 && "$1" = '-' ]]; then
|
||||
echo -
|
||||
return 0
|
||||
fi
|
||||
if [ $# = 0 ]; then
|
||||
die 10 "no files passed, use '-' when reading from pipe (|)"
|
||||
fi
|
||||
local any=0 diagmsgs=/dev/stderr re=$'[\t \n]'
|
||||
[ -n "${QUIET_COMPAT-}" ] && diagmsgs=/dev/null
|
||||
for x in "$@"; do
|
||||
if [ -e "$x" ]; then
|
||||
if [[ "$x" =~ $re ]]; then
|
||||
die 11 "err: filename contains whitespaces: $x."
|
||||
fi
|
||||
echo "$x"
|
||||
any=1
|
||||
else
|
||||
echo >&"$diagmsgs" filtering "$x" out
|
||||
fi
|
||||
done
|
||||
if [ $any = 0 ]; then
|
||||
echo >&"$diagmsgs" 'all files (for given query) filtered out'
|
||||
fi
|
||||
}
|
||||
|
||||
# Basics of regexp explained, as a reference for mostly-C programmers:
|
||||
# (bash) "regexp-$VAR-regexp" - bash' VARs are placed into "QUOTED" strings
|
||||
# /\);?$/ - match end of function declaration, $ is end of string
|
||||
# ^[ \t]* - (heuristic), anything but comment, eg to exclude function docs
|
||||
# /STH/, /END/ - (awk), print all lines sice STH matched, up to END, inclusive
|
||||
|
||||
# "Whitespace only"
|
||||
WB='[ \t\n]'
|
||||
|
||||
# Helpers below print the thing that is looked for, for further grep'ping/etc.
|
||||
# That simplifies process of excluding comments or spares us state machine impl.
|
||||
#
|
||||
# We take advantage of current/common linux codebase formatting here.
|
||||
#
|
||||
# Functions in this section require input file/s passed as args
|
||||
# (usually one, but more could be supplied in case of renames in kernel),
|
||||
# '-' could be used as an (only) file argument to read from stdin/pipe.
|
||||
|
||||
# wrapper over find-something-decl() functions below, to avoid repetition
|
||||
# pass $what as $1, $end as $2, and $files to look in as rest of args
|
||||
function find-decl() {
|
||||
test $# -ge 3 # ensure that there are at least 3 params
|
||||
local what end files
|
||||
what="$1"
|
||||
end="$2"
|
||||
shift 2
|
||||
files="$(filter-out-bad-files "$@")" || die
|
||||
if [ -z "$files" ]; then
|
||||
return 0
|
||||
fi
|
||||
# shellcheck disable=SC2086
|
||||
awk "
|
||||
/^$WB*\*/ {next}
|
||||
$what, $end
|
||||
" $files
|
||||
}
|
||||
|
||||
# yield $1 function declaration (signature), don't pass return type in $1
|
||||
# looks only in files specified ($2, $3...)
|
||||
function find-fun-decl() {
|
||||
test $# -ge 2
|
||||
local what end
|
||||
what="/$WB*([(]\*)?$1$WB*($|[()])/"
|
||||
end='/\);?$/'
|
||||
shift
|
||||
find-decl "$what" "$end" "$@"
|
||||
}
|
||||
|
||||
# yield $1 enum declaration (type/body)
|
||||
function find-enum-decl() {
|
||||
test $# -ge 2
|
||||
local what end
|
||||
what="/^$WB*enum$WB+$1"' \{$/'
|
||||
end='/\};$/'
|
||||
shift
|
||||
find-decl "$what" "$end" "$@"
|
||||
}
|
||||
|
||||
# yield $1 struct declaration (type/body)
|
||||
function find-struct-decl() {
|
||||
test $# -ge 2
|
||||
local what end
|
||||
what="/^$WB*struct$WB+$1"' \{$/'
|
||||
end='/^\};$/' # that's (^) different from enum-decl
|
||||
shift
|
||||
find-decl "$what" "$end" "$@"
|
||||
}
|
||||
|
||||
# yield first line of $1 macro definition
|
||||
function find-macro-decl() {
|
||||
test $# -ge 2
|
||||
local what end
|
||||
# only unindented defines, only whole-word match
|
||||
what="/^#define$WB+$1"'([ \t\(]|$)/'
|
||||
end=1 # only first line; use find-macro-implementation-decl for full body
|
||||
shift
|
||||
find-decl "$what" "$end" "$@"
|
||||
}
|
||||
|
||||
# yield full macro implementation
|
||||
function find-macro-implementation-decl() {
|
||||
test $# -ge 2
|
||||
local what end
|
||||
# only unindented defines, only whole-word match
|
||||
what="/^#define$WB+$1"'([ \t\(]|$)/'
|
||||
# full implementation, until a line not ending in a backslash.
|
||||
# Does not handle macros with comments embedded within the definition.
|
||||
end='/[^\\]$/'
|
||||
shift
|
||||
find-decl "$what" "$end" "$@"
|
||||
}
|
||||
|
||||
# yield first line of $1 typedef definition (simple typedefs only)
|
||||
# this probably won't handle typedef struct { \n int foo;\n};
|
||||
function find-typedef-decl() {
|
||||
test $# -ge 2
|
||||
local what end
|
||||
what="/^typedef .* $1"';$/'
|
||||
end=1
|
||||
shift
|
||||
find-decl "$what" "$end" "$@"
|
||||
}
|
||||
|
||||
# gen() - DSL-like function to wrap around all the other
|
||||
#
|
||||
# syntax:
|
||||
# gen DEFINE if (KIND [METHOD of]) NAME [(matches|lacks) PATTERN|absent] in <list-of-files>
|
||||
|
||||
# where:
|
||||
# DEFINE is HAVE_ or NEED_ #define to print;
|
||||
# `if` is there to just read it easier and made syntax easier to check;
|
||||
#
|
||||
# NAME is the name for what we are looking for;
|
||||
#
|
||||
# KIND specifies what kind of declaration/definition we are looking for,
|
||||
# could be: fun, enum, struct, method, macro, typedef,
|
||||
# 'implementation of macro'
|
||||
# for KIND=method, we are looking for function ptr named METHOD in struct
|
||||
# named NAME (two optional args are then necessary (METHOD & of));
|
||||
#
|
||||
# for KIND='implementation of macro' we are looking for the full
|
||||
# implementation of the macro, not just its first line. This is usually
|
||||
# combined with "matches" or "lacks".
|
||||
#
|
||||
# next [optional] args could be used:
|
||||
# matches PATTERN - use to grep for the PATTERN within definition
|
||||
# (eg, for ext_ack param)
|
||||
# lacks - use to add #define only if there is no match of the PATTERN,
|
||||
# *but* the NAME is *found*
|
||||
# absent - the NAME that we grep for must be not found
|
||||
# (ie: function not exisiting)
|
||||
#
|
||||
# without this optional params, behavior is the same as with
|
||||
# `matches .` - use to grep just for existence of NAME;
|
||||
#
|
||||
# `in` is there to ease syntax, similar to `if` before.
|
||||
#
|
||||
# <list-of-files> is just space-separate list of files to look in,
|
||||
# single (-) for stdin.
|
||||
#
|
||||
# PATTERN is an awk pattern, will be wrapped by two slashes (/)
|
||||
function gen() {
|
||||
test $# -ge 6 || die 20 "too few arguments, $# given, at least 6 needed"
|
||||
local define if_kw kind name in_kw # mandatory
|
||||
local of_kw method_name operator pattern # optional
|
||||
local src_line="${BASH_SOURCE[0]}:${BASH_LINENO[0]}"
|
||||
define="$1"
|
||||
if_kw="$2"
|
||||
kind="$3"
|
||||
local orig_args_cnt=$#
|
||||
shift 3
|
||||
[ "$if_kw" != if ] && die 21 "$src_line: 'if' keyword expected, '$if_kw' given"
|
||||
case "$kind" in
|
||||
fun|enum|struct|macro|typedef)
|
||||
name="$1"
|
||||
shift
|
||||
;;
|
||||
method)
|
||||
test $# -ge 5 || die 22 "$src_line: too few arguments, $orig_args_cnt given, at least 8 needed"
|
||||
method_name="$1"
|
||||
of_kw="$2"
|
||||
name="$3"
|
||||
shift 3
|
||||
[ "$of_kw" != of ] && die 23 "$src_line: 'of' keyword expected, '$of_kw' given"
|
||||
;;
|
||||
implementation)
|
||||
test $# -ge 5 || die 28 "$src_line: too few arguments, $orig_args_cnt given, at least 8 needed"
|
||||
of_kw="$1"
|
||||
kind="$2"
|
||||
name="$3"
|
||||
shift 3
|
||||
[ "$of_kw" != of ] && die 29 "$src_line: 'of' keyword expected, '$of_kw' given"
|
||||
[ "$kind" != macro ] && die 30 "$src_line: implementation only supports 'macro', '$kind' given"
|
||||
kind=macro-implementation
|
||||
;;
|
||||
*) die 24 "$src_line: unknown KIND ($kind) to look for" ;;
|
||||
esac
|
||||
operator="$1"
|
||||
case "$operator" in
|
||||
absent)
|
||||
pattern='.'
|
||||
in_kw="$2"
|
||||
shift 2
|
||||
;;
|
||||
matches|lacks)
|
||||
pattern="$2"
|
||||
in_kw="$3"
|
||||
shift 3
|
||||
;;
|
||||
in)
|
||||
operator=matches
|
||||
pattern='.'
|
||||
in_kw=in
|
||||
shift
|
||||
;;
|
||||
*) die 25 "$src_line: unknown OPERATOR ($operator) to look for" ;;
|
||||
esac
|
||||
[ "$in_kw" != in ] && die 26 "$src_line: 'in' keyword expected, '$in_kw' given"
|
||||
test $# -ge 1 || die 27 "$src_line: too few arguments, at least one filename expected"
|
||||
|
||||
local first_decl=
|
||||
if [ "$kind" = method ]; then
|
||||
first_decl="$(find-struct-decl "$name" "$@")" || exit 40
|
||||
# prepare params for next lookup phase
|
||||
set -- - # overwrite $@ to be single dash (-)
|
||||
name="$method_name"
|
||||
kind=fun
|
||||
elif [[ $# = 1 && "$1" = '-' ]]; then
|
||||
# avoid losing stdin provided to gen() due to redirection (<<<)
|
||||
first_decl="$(cat -)"
|
||||
fi
|
||||
|
||||
# lookup the NAME
|
||||
local body
|
||||
body="$(find-$kind-decl "$name" "$@" <<< "$first_decl")" || exit 41
|
||||
awk -v define="$define" -v pattern="$pattern" -v "$operator"=1 '
|
||||
BEGIN {
|
||||
# prepend "identifier boundary" to pattern, also append
|
||||
# it, but only for patterns not ending with such already
|
||||
#
|
||||
# eg: "foo" -> "\bfoo\b"
|
||||
# "struct foo *" -> "\bstruct foo *"
|
||||
|
||||
# Note that mawk does not support "\b", so we have our
|
||||
# own approximation, NI
|
||||
NI = "[^A-Za-z0-9_]" # "Not an Indentifier"
|
||||
|
||||
if (!match(pattern, NI "$"))
|
||||
pattern = pattern "(" NI "|$)"
|
||||
pattern = "(^|" NI ")" pattern
|
||||
}
|
||||
/./ { not_empty = 1 }
|
||||
$0 ~ pattern { found = 1 }
|
||||
END {
|
||||
if (lacks && !found && not_empty || matches && found || absent && !found)
|
||||
print "#define", define
|
||||
}
|
||||
' <<< "$body"
|
||||
}
|
||||
|
||||
# tell if given flag is enabled in .config
|
||||
# return 0 if given flag is enabled, 1 otherwise
|
||||
# inputs:
|
||||
# $1 - flag to check (whole word, without _MODULE suffix)
|
||||
# env flag $CONFFILE
|
||||
#
|
||||
# there are two "config" formats supported, to ease up integrators lifes
|
||||
# .config (without leading #~ prefix):
|
||||
#~ # CONFIG_ACPI_EC_DEBUGFS is not set
|
||||
#~ CONFIG_ACPI_AC=y
|
||||
#~ CONFIG_ACPI_VIDEO=m
|
||||
# and autoconf.h, which would be:
|
||||
#~ #define CONFIG_ACPI_AC 1
|
||||
#~ #define CONFIG_ACPI_VIDEO_MODULE 1
|
||||
function config_has() {
|
||||
grep -qE "^(#define )?$1((_MODULE)? 1|=m|=y)$" "$CONFFILE"
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
|
||||
#ifndef _KCOMPAT_DEFS_H_
|
||||
#define _KCOMPAT_DEFS_H_
|
||||
|
||||
#ifndef LINUX_VERSION_CODE
|
||||
#include <linux/version.h>
|
||||
#else
|
||||
#ifndef KERNEL_VERSION
|
||||
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
|
||||
#endif
|
||||
#endif /* LINUX_VERSION_CODE */
|
||||
|
||||
#ifndef UTS_RELEASE
|
||||
#include <generated/utsrelease.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Include the definitions file for HAVE/NEED flags for the standard upstream
|
||||
* kernels.
|
||||
*
|
||||
* Then, based on the distribution we detect, load the distribution specific
|
||||
* definitions file that customizes the definitions for the target
|
||||
* distribution.
|
||||
*/
|
||||
#include "kcompat_std_defs.h"
|
||||
|
||||
|
||||
#ifdef RHEL_RELEASE_CODE
|
||||
#include "kcompat_rhel_defs.h"
|
||||
#endif
|
||||
|
||||
#include "kcompat_generated_defs.h"
|
||||
|
||||
#endif /* _KCOMPAT_DEFS_H_ */
|
@ -0,0 +1,14 @@
|
||||
/* Autogenerated for KSRC=/lib/modules/5.10.0-136.12.oe2203sp1/source via kcompat-generator.sh */
|
||||
#ifndef _KCOMPAT_GENERATED_DEFS_H_
|
||||
#define _KCOMPAT_GENERATED_DEFS_H_
|
||||
#define HAVE_AUXILIARY_DEVICE_ID
|
||||
#define HAVE_VIRTIO_PCI_MODERN
|
||||
#define HAVE_VDPA_OPS_RESET
|
||||
#define HAVE_VDPA_MGMTDEV_OPS
|
||||
#define HAVE_VDPA_DEV_SET_CONFIG
|
||||
#define HAVE_VDPA_OPS_DEVICE_FEAT
|
||||
#define HAVE_VDPA_OPS_GET_CONFIG_SIZE
|
||||
#define HAVE_VDPA_OPS_LOG_BASE
|
||||
#define HAVE_STRUCT_PCI_DEV_PTM_ENABLED
|
||||
#define NEED_PCIE_PTM_ENABLED
|
||||
#endif /* _KCOMPAT_GENERATED_DEFS_H_ */
|
@ -0,0 +1,164 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef _KCOMPAT_RHEL_DEFS_H_
|
||||
#define _KCOMPAT_RHEL_DEFS_H_
|
||||
|
||||
/* This is the RedHat Enterprise Linux distribution specific definitions file.
|
||||
* It defines what features need backports for a given version of the RHEL
|
||||
* kernel.
|
||||
*
|
||||
* It checks the RHEL_RELEASE_CODE and RHEL_RELEASE_VERSION macros to decide
|
||||
* what support the target kernel has.
|
||||
*
|
||||
* It assumes that kcompat_std_defs.h has already been processed, and will
|
||||
* #define or #undef any flags that have changed based on backports done by
|
||||
* RHEL.
|
||||
*/
|
||||
|
||||
#if !RHEL_RELEASE_CODE
|
||||
#error "RHEL_RELEASE_CODE is 0 or undefined"
|
||||
#endif
|
||||
|
||||
#ifndef RHEL_RELEASE_VERSION
|
||||
#error "RHEL_RELEASE_VERSION is undefined"
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,3))
|
||||
#define NEED_NETDEV_TXQ_BQL_PREFETCH
|
||||
#else /* >= 7.3 */
|
||||
#endif /* 7.3 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,4))
|
||||
#define NEED_BUILD_BUG_ON
|
||||
#else /* >= 7.4 */
|
||||
#define HAVE_RHEL7_EXTENDED_OFFLOAD_STATS
|
||||
#define HAVE_INCLUDE_BITFIELD
|
||||
#endif /* 7.4 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,5))
|
||||
#else /* >= 7.5 */
|
||||
#define HAVE_TCF_EXTS_TO_LIST
|
||||
#define HAVE_FLOW_DISSECTOR_KEY_IP
|
||||
#endif /* 7.5 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,6))
|
||||
#undef HAVE_XDP_BUFF_RXQ
|
||||
#undef HAVE_XDP_RXQ_INFO_REG_3_PARAMS
|
||||
#else /* >= 7.6 */
|
||||
#undef NEED_JIFFIES_64_TIME_IS_MACROS
|
||||
#undef NEED_TC_CLS_CAN_OFFLOAD_AND_CHAIN0
|
||||
#undef NEED_TC_SETUP_QDISC_MQPRIO
|
||||
#endif /* 7.6 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,7))
|
||||
#else /* >= 7.7 */
|
||||
#define HAVE_DEVLINK_PORT_ATTRS_SET_PORT_FLAVOUR
|
||||
#define HAVE_ETHTOOL_NEW_100G_BITS
|
||||
#undef NEED_NETDEV_TX_SENT_QUEUE
|
||||
#undef NEED_IN_TASK
|
||||
#define HAVE_FLOW_DISSECTOR_KEY_ENC_IP
|
||||
#endif /* 7.7 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8,0))
|
||||
#else /* >= 8.0 */
|
||||
#undef HAVE_TCF_EXTS_TO_LIST
|
||||
#undef HAVE_ETHTOOL_NEW_100G_BITS
|
||||
#define HAVE_NDO_OFFLOAD_STATS
|
||||
#undef HAVE_RHEL7_EXTENDED_OFFLOAD_STATS
|
||||
#define HAVE_TCF_EXTS_FOR_EACH_ACTION
|
||||
/* 7.7 undefs it due to a backport in 7.7+, but 8.0 needs it still */
|
||||
#define NEED_NETDEV_TX_SENT_QUEUE
|
||||
#endif /* 8.0 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8,1))
|
||||
#define NEED_IDA_ALLOC_MIN_MAX_RANGE_FREE
|
||||
#define NEED_FLOW_MATCH
|
||||
#else /* >= 8.1 */
|
||||
#define HAVE_ETHTOOL_NEW_100G_BITS
|
||||
#undef NEED_IDA_ALLOC_MIN_MAX_RANGE_FREE
|
||||
#undef NEED_FLOW_MATCH
|
||||
#undef NEED_NETDEV_TX_SENT_QUEUE
|
||||
#undef NEED_INDIRECT_CALL_WRAPPER_MACROS
|
||||
#define HAVE_INDIRECT_CALL_WRAPPER_HEADER
|
||||
#define HAVE_GRETAP_TYPE
|
||||
#define HAVE_GENEVE_TYPE
|
||||
#define HAVE_VXLAN_TYPE
|
||||
#define HAVE_LINKMODE
|
||||
#endif /* 8.1 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8,2))
|
||||
#else /* >= 8.2 */
|
||||
#undef NEED_DEVLINK_FLASH_UPDATE_STATUS_NOTIFY
|
||||
#undef NEED_SKB_FRAG_OFF
|
||||
#undef NEED_SKB_FRAG_OFF_ADD
|
||||
#undef NEED_FLOW_INDR_BLOCK_CB_REGISTER
|
||||
#define HAVE_FLOW_INDR_BLOCK_LOCK
|
||||
#define HAVE_DEVLINK_PORT_ATTRS_SET_SWITCH_ID
|
||||
#define HAVE_NETDEV_SB_DEV
|
||||
#endif /* 8.2 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8,3))
|
||||
#else /* >= 8.3 */
|
||||
#undef NEED_CPU_LATENCY_QOS_RENAME
|
||||
#undef NEED_DEVLINK_REGION_CREATE_OPS
|
||||
#define HAVE_RT_IRQ_SCHED_FIX
|
||||
#endif /* 8.3 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8,4))
|
||||
#else /* >= 8.4 */
|
||||
#undef NEED_DEVLINK_PORT_ATTRS_SET_STRUCT
|
||||
#undef NEED_DEVLINK_FLASH_UPDATE_TIMEOUT_NOTIFY
|
||||
#undef HAVE_XDP_QUERY_PROG
|
||||
#define HAVE_AF_XDP_ZC_SUPPORT
|
||||
#define HAVE_MEM_TYPE_XSK_BUFF_POOL
|
||||
#define HAVE_NDO_XSK_WAKEUP
|
||||
#define XSK_UMEM_RETURNS_XDP_DESC
|
||||
#undef NEED_XSK_UMEM_GET_RX_FRAME_SIZE
|
||||
#define HAVE_ETHTOOL_COALESCE_PARAMS_SUPPORT
|
||||
#define HAVE_PTP_FIND_PIN_UNLOCKED
|
||||
#endif /* 8.4 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8,5))
|
||||
#else /* >= 8.5 */
|
||||
#undef HAVE_NAPI_BUSY_LOOP
|
||||
#undef HAVE_XDP_RXQ_INFO_REG_3_PARAMS
|
||||
#undef NEED_XSK_BUFF_DMA_SYNC_FOR_CPU
|
||||
#define NO_XDP_QUERY_XSK_UMEM
|
||||
#undef NEED_XSK_BUFF_POOL_RENAME
|
||||
#define HAVE_NETDEV_BPF_XSK_POOL
|
||||
#define HAVE_AF_XDP_NETDEV_UMEM
|
||||
#define HAVE_DEVLINK_OPS_CREATE_DEL
|
||||
#endif /* 8.5 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8,7))
|
||||
#else /* >= 8.7 */
|
||||
#undef NEED_DEVLINK_ALLOC_SETS_DEV
|
||||
#define HAVE_DEVLINK_SET_STATE_3_PARAM
|
||||
#endif /* 8.7 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(9,0))
|
||||
#else /* >= 9.0 */
|
||||
#define HAVE_XDP_BUFF_RXQ
|
||||
#endif /* 9.0 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(9,1))
|
||||
#else /* >= 9.1 */
|
||||
#undef HAVE_PASID_SUPPORT
|
||||
#endif /* 9.1 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#endif /* _KCOMPAT_RHEL_DEFS_H_ */
|
@ -0,0 +1,268 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef _KCOMPAT_STD_DEFS_H_
|
||||
#define _KCOMPAT_STD_DEFS_H_
|
||||
|
||||
/* This file contains the definitions for what kernel features need backports
|
||||
* for a given kernel. It targets only the standard stable kernel releases.
|
||||
* It must check only LINUX_VERSION_CODE and assume the kernel is a standard
|
||||
* release, and not a custom distribution.
|
||||
*
|
||||
* It must define HAVE_<FLAG> and NEED_<FLAG> for features. It must not
|
||||
* implement any backports, instead leaving the implementation to the
|
||||
* kcompat_impl.h header.
|
||||
*
|
||||
* If a feature can be easily implemented as a replacement macro or fully
|
||||
* backported, use a NEED_<FLAG> to indicate that the feature needs
|
||||
* a backport. (If NEED_<FLAG> is undefined, then no backport for that feature
|
||||
* is needed).
|
||||
*
|
||||
* If a feature cannot be easily implemented in kcompat directly, but
|
||||
* requires drivers to make specific changes such as stripping out an entire
|
||||
* feature or modifying a function pointer prototype, use a HAVE_<FLAG>.
|
||||
*/
|
||||
|
||||
#ifndef LINUX_VERSION_CODE
|
||||
#error "LINUX_VERSION_CODE is undefined"
|
||||
#endif
|
||||
|
||||
#ifndef KERNEL_VERSION
|
||||
#error "KERNEL_VERSION is undefined"
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0))
|
||||
#else /* >= 4,8,0 */
|
||||
#define HAVE_TCF_EXTS_TO_LIST
|
||||
#define HAVE_PCI_ALLOC_IRQ
|
||||
#endif /* 4,8,0 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0))
|
||||
#define NEED_JIFFIES_64_TIME_IS_MACROS
|
||||
#else /* >= 4,9,0 */
|
||||
#define HAVE_KTHREAD_DELAYED_API
|
||||
#define HAVE_NDO_OFFLOAD_STATS
|
||||
#define HAVE_INCLUDE_BITFIELD
|
||||
#endif /* 4,9,0 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,9,62))
|
||||
#define NEED_IN_TASK
|
||||
#else /* >= 4,9,62 */
|
||||
#endif /* 4,9,62 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,12,0))
|
||||
#else /* >= 4,12,0 */
|
||||
#define HAVE_NAPI_BUSY_LOOP
|
||||
#endif /* 4,12,0 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,13,0))
|
||||
#else /* >= 4,13,0 */
|
||||
#define HAVE_FLOW_DISSECTOR_KEY_IP
|
||||
#endif /* 4,13,0 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0))
|
||||
#define NEED_TC_SETUP_QDISC_MQPRIO
|
||||
#define NEED_NETDEV_XDP_STRUCT
|
||||
#else /* >= 4,15,0 */
|
||||
#define HAVE_TC_CB_AND_SETUP_QDISC_MQPRIO
|
||||
#define HAVE_NDO_BPF
|
||||
#endif /* 4,15,0 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,16,0))
|
||||
#define NEED_TC_CLS_CAN_OFFLOAD_AND_CHAIN0
|
||||
#else /* >= 4,16,0 */
|
||||
#define HAVE_XDP_BUFF_RXQ
|
||||
#define HAVE_XDP_RXQ_INFO_REG_3_PARAMS
|
||||
#endif /* 4,16,0 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,17,0))
|
||||
#define NEED_CONVERT_ART_NS_TO_TSC
|
||||
#else /* >= 4,17,0 */
|
||||
#endif /* 4,17,0 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,18,0))
|
||||
#define NEED_MACVLAN_ACCEL_PRIV
|
||||
#define NEED_MACVLAN_RELEASE_L2FW_OFFLOAD
|
||||
#define NEED_MACVLAN_SUPPORTS_DEST_FILTER
|
||||
#else /* >= 4,18,0 */
|
||||
#define HAVE_DEVLINK_PORT_ATTRS_SET_PORT_FLAVOUR
|
||||
#endif /* 4,18,0 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,19,0))
|
||||
#define NEED_IDA_ALLOC_MIN_MAX_RANGE_FREE
|
||||
#else /* >= 4,19,0 */
|
||||
#undef HAVE_TCF_EXTS_TO_LIST
|
||||
#define HAVE_TCF_EXTS_FOR_EACH_ACTION
|
||||
#define HAVE_TC_ETF_QOPT_OFFLOAD
|
||||
#define HAVE_FLOW_DISSECTOR_KEY_ENC_IP
|
||||
#endif /* 4,19,0 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,20,0))
|
||||
#define NEED_NETDEV_TX_SENT_QUEUE
|
||||
#else /* >= 4.20.0 */
|
||||
#define HAVE_VXLAN_TYPE
|
||||
#define HAVE_LINKMODE
|
||||
#endif /* 4.20.0 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0))
|
||||
#define NEED_INDIRECT_CALL_WRAPPER_MACROS
|
||||
#else /* >= 5.0.0 */
|
||||
#define HAVE_GRETAP_TYPE
|
||||
#define HAVE_GENEVE_TYPE
|
||||
#define HAVE_INDIRECT_CALL_WRAPPER_HEADER
|
||||
#endif /* 5.0.0 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,1,0))
|
||||
#define NEED_FLOW_MATCH
|
||||
#else /* >= 5.1.0 */
|
||||
#define HAVE_ETHTOOL_200G_BITS
|
||||
#define HAVE_ETHTOOL_NEW_100G_BITS
|
||||
#endif /* 5.1.0 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,2,0))
|
||||
#else /* >= 5.2.0 */
|
||||
#define HAVE_DEVLINK_PORT_ATTRS_SET_SWITCH_ID
|
||||
#endif /* 5.2.0 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,3,0))
|
||||
#define NEED_DEVLINK_FLASH_UPDATE_STATUS_NOTIFY
|
||||
#else /* >= 5.3.0 */
|
||||
#endif /* 5.3.0 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0))
|
||||
#define NEED_SKB_FRAG_OFF_ADD
|
||||
#define NEED_SKB_FRAG_OFF
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(4,14,241) && \
|
||||
LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0))
|
||||
#undef NEED_SKB_FRAG_OFF
|
||||
#endif /* > 4.14.241 && < 4.15.0 */
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(4,19,200) && \
|
||||
LINUX_VERSION_CODE < KERNEL_VERSION(4,20,0))
|
||||
#undef NEED_SKB_FRAG_OFF
|
||||
#endif /* > 4.19.200 && < 4.20.0 */
|
||||
|
||||
#define NEED_FLOW_INDR_BLOCK_CB_REGISTER
|
||||
#else /* >= 5.4.0 */
|
||||
#define HAVE_FLOW_INDR_BLOCK_LOCK
|
||||
#define HAVE_XSK_UNALIGNED_CHUNK_PLACEMENT
|
||||
#endif /* 5.4.0 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,7,0))
|
||||
#define NEED_DEVLINK_REGION_CREATE_OPS
|
||||
#define NEED_CPU_LATENCY_QOS_RENAME
|
||||
#else /* >= 5.7.0 */
|
||||
#define HAVE_PTP_FIND_PIN_UNLOCKED
|
||||
#endif /* 5.7.0 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,8,0))
|
||||
#define NEED_XSK_UMEM_GET_RX_FRAME_SIZE
|
||||
#else /* >= 5.8.0 */
|
||||
#undef HAVE_XSK_UNALIGNED_CHUNK_PLACEMENT
|
||||
#define HAVE_RT_IRQ_SCHED_FIX
|
||||
#endif /* 5.8.0 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,9,0))
|
||||
#define NEED_DEVLINK_PORT_ATTRS_SET_STRUCT
|
||||
#define HAVE_XDP_QUERY_PROG
|
||||
#define NEED_INDIRECT_CALL_3_AND_4
|
||||
#else /* >= 5.9.0 */
|
||||
#define HAVE_TASKLET_SETUP
|
||||
#endif /* 5.9.0 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,10,0))
|
||||
#define NEED_DEVLINK_FLASH_UPDATE_TIMEOUT_NOTIFY
|
||||
#define NEED_XSK_BUFF_DMA_SYNC_FOR_CPU
|
||||
#define NEED_XSK_BUFF_POOL_RENAME
|
||||
#else /* >= 5.10.0 */
|
||||
#define HAVE_UDP_TUNNEL_NIC_SHARED
|
||||
#define HAVE_NETDEV_BPF_XSK_POOL
|
||||
#endif /* 5.10.0 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,11,0))
|
||||
#else /* >= 5.11.0 */
|
||||
#define HAVE_XSK_BATCHED_DESCRIPTOR_INTERFACES
|
||||
#define HAVE_PASID_SUPPORT
|
||||
#undef HAVE_XDP_RXQ_INFO_REG_3_PARAMS
|
||||
#define HAVE_XSK_TX_PEEK_RELEASE_DESC_BATCH_3_PARAMS
|
||||
#endif /* 5.11.0 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,12,0))
|
||||
#define NEED_EXPORT_INDIRECT_CALLABLE
|
||||
#else /* >= 5.12.0 */
|
||||
#define HAVE_DEVLINK_OPS_CREATE_DEL
|
||||
#endif /* 5.12.0 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,13,0))
|
||||
/* HAVE_KOBJ_IN_MDEV_PARENT_OPS_CREATE
|
||||
*
|
||||
* create api changed as part of the commit c2ef2f50ad0c( vfio/mdev: Remove
|
||||
* kobj from mdev_parent_ops->create())
|
||||
*
|
||||
* if flag is defined use the old API else new API
|
||||
*/
|
||||
#define HAVE_KOBJ_IN_MDEV_PARENT_OPS_CREATE
|
||||
#define HAVE_DEV_IN_MDEV_API
|
||||
#else /* >= 5.13.0 */
|
||||
#define HAVE_XPS_MAP_TYPE
|
||||
#endif /* 5.13.0 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,14,0))
|
||||
#else /* >= 5.14.0 */
|
||||
#define HAVE_TTY_WRITE_ROOM_UINT
|
||||
#endif /* 5.14.0 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,15,0))
|
||||
#define NEED_DEVLINK_ALLOC_SETS_DEV
|
||||
#else /* >= 5.15.0 */
|
||||
#define HAVE_DEVICE_IN_MDEV_PARENT_OPS
|
||||
#define NEED_PCI_IOV_VF_ID
|
||||
#define HAVE_DEVLINK_SET_STATE_3_PARAM
|
||||
#endif /* 5.15.0 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,16,0))
|
||||
#else /* >= 5.16.0 */
|
||||
#undef HAVE_PASID_SUPPORT
|
||||
#define HAVE_XSK_BATCHED_RX_ALLOC
|
||||
#endif /* 5.16.0 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0))
|
||||
#else /* >=5.18.0*/
|
||||
#undef NEED_PCI_IOV_VF_ID
|
||||
#define HAVE_GTP_SUPPORT
|
||||
#undef HAVE_XSK_TX_PEEK_RELEASE_DESC_BATCH_3_PARAMS
|
||||
#endif /* 5.18.0 */
|
||||
|
||||
/*****************************************************************************/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6,1,0))
|
||||
#else /* >=6.1.0 */
|
||||
#define HAVE_FLOW_DISSECTOR_KEY_L2TPV3
|
||||
#define HAVE_TTY_TERMIOS_CONST_STRUCT
|
||||
#endif /* 6.1.0 */
|
||||
|
||||
#endif /* _KCOMPAT_STD_DEFS_H_ */
|
235
LingYaoSNIC/HW/kernel/kernel-crete-front-driver/scripts/check_aux_bus
Executable file
235
LingYaoSNIC/HW/kernel/kernel-crete-front-driver/scripts/check_aux_bus
Executable file
@ -0,0 +1,235 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# Copyright (C) 2021 - 2023 Intel Corporation
|
||||
#
|
||||
# Helper script to detect if auxiliary bus support. This script
|
||||
#
|
||||
# returns 0 when:
|
||||
# - CONFIG_AUXILIARY_BUS=y
|
||||
# - auxiliary_bus.h was found
|
||||
#
|
||||
# Returning 0 means the driver build/install doesn't need OOT
|
||||
# auxiliary bus
|
||||
#
|
||||
# returns 1 when:
|
||||
# - CONFIG_AUXILIARY_BUS=n (or any value that's not "=y")
|
||||
# - kernel configuration was incorrect
|
||||
# - kernel configuration file was not found
|
||||
#
|
||||
# Returning 1 means something bad/unexpected happened and the
|
||||
# driver build/install should treat this as a failure
|
||||
#
|
||||
# returns 2 when:
|
||||
# - When OOT auxiliary is needed regardless if a previous OOT
|
||||
# auxiliary was already. This is done because the driver
|
||||
# always needs to build against auxiliary.o to avoid
|
||||
# warnings/errors since auxiliary.o is built-in to the
|
||||
# driver's makefile
|
||||
#
|
||||
# Returning 2 means the driver build/install needs OOT auxiliary
|
||||
# bus
|
||||
#
|
||||
# returns 3 when:
|
||||
# - A file and/or directory does not exist
|
||||
#
|
||||
# Returning 3 means something bad/unexpected happened and the
|
||||
# driver build/install should treat this as a failure
|
||||
#
|
||||
# Note: when ksrc and build-kernel are both specified on the
|
||||
# command line and build-kernel is not in the same location
|
||||
# as ksrc, then ksrc takes precedence. For example:
|
||||
# ./check_aux_bus --ksrc=/lib/modules/5.8.0/source --build-kernel=5.10.0
|
||||
#
|
||||
# In this case the kernel config file won't be searched for and
|
||||
# the script will only check to see if the in-tree/OOT auxiliary_bus.h
|
||||
# file exists at ksrc.
|
||||
|
||||
msg()
|
||||
{
|
||||
if [ $verbose == 1 ]; then
|
||||
echo -e $1
|
||||
fi
|
||||
}
|
||||
|
||||
exit_builtin_auxiliary_enabled() { exit 0; }
|
||||
exit_kconfig_invalid() { exit 1; }
|
||||
exit_need_oot_auxiliary() { exit 2; }
|
||||
exit_not_found_failure() { exit 3; }
|
||||
|
||||
find_aux_bus_inc()
|
||||
{
|
||||
aux_bus_inc=$(find -L ${ksrc} -name "auxiliary_bus.h")
|
||||
msg "auxiliary_bus.h location: ${aux_bus_inc}"
|
||||
}
|
||||
|
||||
LINUX_INCLUDE_DIR="include/linux"
|
||||
|
||||
set_build_kernel()
|
||||
{
|
||||
build_kernel=$(uname -r)
|
||||
}
|
||||
|
||||
find_kernel_source()
|
||||
{
|
||||
# All the default places to look for kernel source
|
||||
test_dirs=(/lib/modules/${build_kernel}/source \
|
||||
/lib/modules/${build_kernel}/build \
|
||||
/usr/src/linux-${build_kernel} \
|
||||
/usr/src/linux-$(echo ${build_kernel} | sed 's/-.*//') \
|
||||
/usr/src/kernel-headers-${build_kernel} \
|
||||
/usr/src/kernel-source-${build_kernel} \
|
||||
/usr/src/linux-$(echo ${build_kernel} | sed 's/\([0-9]*\.[0-9]*\)\..*/\1/') \
|
||||
/usr/src/linux \
|
||||
/usr/src/kernels/${build_kernel} \
|
||||
/usr/src/kernels)
|
||||
|
||||
# Save the first valid kernel source path
|
||||
for dir in "${test_dirs[@]}"; do
|
||||
if [ -d ${dir}/${LINUX_INCLUDE_DIR} ]; then
|
||||
ksrc=${dir}
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -z ${ksrc} ]; then
|
||||
echo "*** Kernel header files not in any of the expected locations."
|
||||
echo "*** Install the appropriate kernel development package, e.g."
|
||||
echo "kernel-devel, for building kernel modules and try again"
|
||||
exit_not_found_failure
|
||||
fi
|
||||
}
|
||||
|
||||
find_config_file()
|
||||
{
|
||||
# only search for kernel .config file if build_kernel is pointing
|
||||
# in the same tree as ksrc (see not about ksrc and build_kernel
|
||||
# both set in the scripts header comment)
|
||||
if [[ "$ksrc" != *"/lib/modules/${build_kernel}"* ]]; then
|
||||
msg "ksrc=$ksrc not the same as location generated from build_kernel=\"/lib/modules/${build_kernel}\", not searching for kernel .config file"
|
||||
else
|
||||
kbuild_dir="/lib/modules/${build_kernel}/build"
|
||||
|
||||
file_locations=(${kbuild_dir}/include/generated/autoconf.h \
|
||||
${kbuild_dir}/include/linux/autoconf.h \
|
||||
/boot/bmlinux.autoconf.h)
|
||||
|
||||
for file in "${file_locations[@]}"; do
|
||||
if [ -f ${file} ]; then
|
||||
kconfig=${file}
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -z ${kconfig} ]; then
|
||||
msg "Kernel config file not found at any of the expected locations."
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
get_config_auxiliary_bus()
|
||||
{
|
||||
# CONFIG_AUXILIARY_BUS=0 corresponds to CONFIG_AUXILIARY_BUS=n
|
||||
# CONFIG_AUXILIARY_BUS=1 corresponds to CONFIG_AUXILIARY_BUS=y
|
||||
# CONFIG_AUXILIARY_BUS= corresponds to CONFIG_AUXILIARY_BUS not available in the kernel
|
||||
CONFIG_AUXILIARY_BUS=$(grep CONFIG_AUXILIARY_BUS ${kconfig} | awk -F" " '{print $3}')
|
||||
msg "CONFIG_AUXILIARY_BUS=${CONFIG_AUXILIARY_BUS}"
|
||||
}
|
||||
|
||||
ksrc=""
|
||||
build_kernel=""
|
||||
verbose=0
|
||||
|
||||
usage()
|
||||
{
|
||||
script=$(basename $0)
|
||||
echo -e "usage:"
|
||||
echo -e "\t$script [options]"
|
||||
echo -e "\n\toptions:"
|
||||
echo -e "\t -v, --verbose"
|
||||
echo -e "\t -h, --help"
|
||||
echo -e "\n\t run script against specified kernel source"
|
||||
echo -e "\t -k, --ksrc \"/lib/modules/5.12.0/source\""
|
||||
echo -e "\n\t run script with kernel version (kernel version used to find kernel source programatically)"
|
||||
echo -e "\t -b, --build-kernel \"5.8.0\""
|
||||
}
|
||||
|
||||
options=$(getopt -o "k:b:vh" --long ksrc:,build-kernel:,verbose,help -- "$@")
|
||||
eval set -- "$options"
|
||||
while :; do
|
||||
case $1 in
|
||||
-k|--ksrc) ksrc=$2; shift;;
|
||||
-b|--build-kernel) build_kernel=$2; shift;;
|
||||
-v|--verbose) verbose=1 ;;
|
||||
-h|--help) usage && exit 0;;
|
||||
--) shift; break;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [ $verbose == 1 ]; then
|
||||
set -x
|
||||
fi
|
||||
|
||||
# both build_kernel and ksrc are unset so programatically determine build_kernel
|
||||
if [ -z $build_kernel ] && [ -z $ksrc ]; then
|
||||
set_build_kernel
|
||||
fi
|
||||
|
||||
# only programatically search for kernel source if ksrc not set on command line
|
||||
if [ -z $ksrc ]; then
|
||||
find_kernel_source
|
||||
fi
|
||||
|
||||
find_config_file
|
||||
|
||||
if [ ! -z $kconfig ]; then
|
||||
# if we found the kernel .config file then exit the script based on various
|
||||
# conditions that depend on the CONFIG_AUXILIARY_BUS string being found
|
||||
get_config_auxiliary_bus
|
||||
|
||||
if [ -z "$CONFIG_AUXILIARY_BUS" ]; then
|
||||
msg "CONFIG_AUXILIARY_BUS not found in ${kconfig}."
|
||||
# CONFIG_AUXILIARY_BUS string was not found, so OOT auxiliary is needed
|
||||
exit_need_oot_auxiliary
|
||||
elif [ "$CONFIG_AUXILIARY_BUS" = "1" ]; then
|
||||
msg "CONFIG_AUXILIARY_BUS=y in ${kconfig}."
|
||||
# CONFIG_AUXILIARY_BUS=y, so OOT auxiliary is not needed
|
||||
exit_builtin_auxiliary_enabled
|
||||
else
|
||||
msg ""
|
||||
msg "kernel $build_kernel supports auxiliary bus, but CONFIG_AUXILIARY_BUS"
|
||||
msg "is not set in ${kconfig}. Rebuild your kernel with"
|
||||
msg "CONFIG_AUXILIARY_BUS=y"
|
||||
msg ""
|
||||
# CONFIG_AUXILIARY_BUS is not "=y", but the string was found, so report
|
||||
# the failure so it can be used to fail build/install
|
||||
exit_kconfig_invalid
|
||||
fi
|
||||
else
|
||||
if [ ! -d ${ksrc}/${LINUX_INCLUDE_DIR} ] && [ ! -d ${ksrc}/source/${LINUX_INCLUDE_DIR} ]; then
|
||||
echo "${ksrc}/${LINUX_INCLUDE_DIR} and ${ksrc}/source/${LINUX_INCLUDE_DIR} do not exist"
|
||||
exit_not_found_failure
|
||||
fi
|
||||
|
||||
# We didn't find a kernel .config file, so check to see if auxiliary_bus.h
|
||||
# is found in the kernel source include directory
|
||||
find_aux_bus_inc
|
||||
|
||||
if [ -f "$aux_bus_inc" ]; then
|
||||
# AUXILIARY_MODULE_PREFIX is defined only in out-of-tree auxiliary bus
|
||||
if [ $(grep -c AUXILIARY_MODULE_PREFIX $aux_bus_inc) -eq 0 ]; then
|
||||
msg "in-tree auxiliary_bus.h found at ${ksrc}/${LINUX_INCLUDE_DIR}"
|
||||
# If auxiliary_bus.h is included at ${ksrc} and it isn't our OOT version, then
|
||||
# don't build OOT auxiliary as part of the driver makefile
|
||||
exit_builtin_auxiliary_enabled
|
||||
else
|
||||
msg "OOT auxiliary_bus.h found at ${ksrc}/${LINUX_INCLUDE_DIR}"
|
||||
# If auxiliary bus is included at ${ksrc} and it is our OOT version, then
|
||||
# build OOT auxiliary as part of the driver makefile
|
||||
exit_need_oot_auxiliary
|
||||
fi
|
||||
else
|
||||
msg "auxiliary_bus.h not found at ${ksrc}/${LINUX_INCLUDE_DIR}"
|
||||
exit_need_oot_auxiliary
|
||||
fi
|
||||
fi
|
86
LingYaoSNIC/HW/kernel/kernel-crete-front-driver/scripts/set_arfs
Executable file
86
LingYaoSNIC/HW/kernel/kernel-crete-front-driver/scripts/set_arfs
Executable file
@ -0,0 +1,86 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# Copyright (C) 2020 - 2023 Intel Corporation
|
||||
#
|
||||
# Attempt a basic setup of adaptive receive flow steering
|
||||
# also known as aRFS. aRFS will automatically at runtime
|
||||
# use ntuple rules to direct receive traffic to the same
|
||||
# rx queue (matched by queue number) as was used for the
|
||||
# application that was transmitting. Most useful for
|
||||
# TCP workloads and latency sensitive TCP connections.
|
||||
#
|
||||
# typical usage is (as root):
|
||||
# set_arfs -s flow_entries eth1 <eth2> <eth3>
|
||||
#
|
||||
# to get help:
|
||||
# set_arfs
|
||||
|
||||
usage()
|
||||
{
|
||||
echo
|
||||
echo "Usage: $0 [-s flow_entries] <interface> ..."
|
||||
echo " Options: "
|
||||
echo " -s number of socket flow entries"
|
||||
echo " Examples:"
|
||||
echo " $0 eth1 eth2 # eth1 and eth2 use default flow_entries"
|
||||
echo " $0 -s flow_entries eth1 # eth1 use specified flow_entries"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# offer some help
|
||||
if [ "$1" == "-h" ] || [ "$1" == "--help" ]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# if -s and a value specified, then use them.
|
||||
if [ "$1" == "-s" ]; then
|
||||
FLOW_ENTRIES=$2
|
||||
shift
|
||||
shift
|
||||
fi
|
||||
|
||||
# append the interfaces listed to the string with spaces
|
||||
while [ "$#" -ne "0" ] ; do
|
||||
IFACES+=" $1"
|
||||
shift
|
||||
done
|
||||
|
||||
# for now the user must specify interfaces
|
||||
if [ -z "$IFACES" ]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# provide a default flow num value, typically 2048 per queue
|
||||
# is useful, but if there are many queues then maybe a smaller
|
||||
# value per-queue is good enough.
|
||||
if [ -z "$FLOW_ENTRIES" ]; then
|
||||
FLOW_ENTRIES=32768
|
||||
fi
|
||||
|
||||
set_arfs()
|
||||
{
|
||||
echo $FLOW_ENTRIES > /proc/sys/net/core/rps_sock_flow_entries
|
||||
echo -n "done: "
|
||||
grep -H . /proc/sys/net/core/rps_sock_flow_entries
|
||||
for IFACE in $IFACES; do
|
||||
QDIR="/sys/class/net/$IFACE/queues"
|
||||
QUEUES=`ls -1 -d $QDIR/rx-*`
|
||||
QUEUES_COUNT=`ls -1 -d $QDIR/rx-* | wc -l`
|
||||
sockTrack=$((FLOW_ENTRIES / QUEUES_COUNT))
|
||||
if [ -z `ls $QDIR/rx-0/rps_flow_cnt` ]; then
|
||||
echo "ERROR: aRFS is not supported on $IFACE"
|
||||
exit 2
|
||||
fi
|
||||
n=0
|
||||
for i in $QUEUES; do
|
||||
echo $sockTrack > $i/rps_flow_cnt
|
||||
echo -n "Queue $((n++)) done: "
|
||||
grep -H . $i/rps_flow_cnt
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
set_arfs
|
336
LingYaoSNIC/HW/kernel/kernel-crete-front-driver/scripts/set_irq_affinity
Executable file
336
LingYaoSNIC/HW/kernel/kernel-crete-front-driver/scripts/set_irq_affinity
Executable file
@ -0,0 +1,336 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# Copyright (C) 2015 - 2023 Intel Corporation
|
||||
#
|
||||
# Affinitize interrupts to cores
|
||||
#
|
||||
# typical usage is (as root):
|
||||
# set_irq_affinity -x local eth1 <eth2> <eth3>
|
||||
# set_irq_affinity -s eth1
|
||||
#
|
||||
# to get help:
|
||||
# set_irq_affinity
|
||||
|
||||
usage()
|
||||
{
|
||||
echo
|
||||
echo "Usage: option -s <interface> to show current settings only"
|
||||
echo "Usage: $0 [-x|-X] [all|local|remote [<node>]|one <core>|custom|<cores>] <interface> ..."
|
||||
echo " Options: "
|
||||
echo " -s Shows current affinity settings"
|
||||
echo " -x Configure XPS as well as smp_affinity"
|
||||
echo " -X Disable XPS but set smp_affinity"
|
||||
echo " [all] is the default value"
|
||||
echo " [remote [<node>]] can be followed by a specific node number"
|
||||
echo " Examples:"
|
||||
echo " $0 -s eth1 # Show settings on eth1"
|
||||
|
||||
echo " $0 all eth1 eth2 # eth1 and eth2 to all cores"
|
||||
echo " $0 one 2 eth1 # eth1 to core 2 only"
|
||||
echo " $0 local eth1 # eth1 to local cores only"
|
||||
echo " $0 remote eth1 # eth1 to remote cores only"
|
||||
echo " $0 custom eth1 # prompt for eth1 interface"
|
||||
echo " $0 0-7,16-23 eth0 # eth1 to cores 0-7 and 16-23"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
usageX()
|
||||
{
|
||||
echo "options -x and -X cannot both be specified, pick one"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [ "$1" == "-x" ]; then
|
||||
XPS_ENA=1
|
||||
shift
|
||||
fi
|
||||
|
||||
if [ "$1" == "-s" ]; then
|
||||
SHOW=1
|
||||
echo Show affinity settings
|
||||
shift
|
||||
fi
|
||||
|
||||
if [ "$1" == "-X" ]; then
|
||||
if [ -n "$XPS_ENA" ]; then
|
||||
usageX
|
||||
fi
|
||||
XPS_DIS=2
|
||||
shift
|
||||
fi
|
||||
|
||||
if [ "$1" == -x ]; then
|
||||
usageX
|
||||
fi
|
||||
|
||||
if [ -n "$XPS_ENA" ] && [ -n "$XPS_DIS" ]; then
|
||||
usageX
|
||||
fi
|
||||
|
||||
if [ -z "$XPS_ENA" ]; then
|
||||
XPS_ENA=$XPS_DIS
|
||||
fi
|
||||
|
||||
SED=`which sed`
|
||||
if [[ ! -x $SED ]]; then
|
||||
echo " $0: ERROR: sed not found in path, this script requires sed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
num='^[0-9]+$'
|
||||
|
||||
# search helpers
|
||||
NOZEROCOMMA="s/^[0,]*//"
|
||||
# Vars
|
||||
AFF=$1
|
||||
shift
|
||||
|
||||
case "$AFF" in
|
||||
remote) [[ $1 =~ $num ]] && rnode=$1 && shift ;;
|
||||
one) [[ $1 =~ $num ]] && cnt=$1 && shift ;;
|
||||
all) ;;
|
||||
local) ;;
|
||||
custom) ;;
|
||||
[0-9]*) ;;
|
||||
-h|--help) usage ;;
|
||||
"") usage ;;
|
||||
*) IFACES=$AFF && AFF=all ;; # Backwards compat mode
|
||||
esac
|
||||
|
||||
# append the interfaces listed to the string with spaces
|
||||
while [ "$#" -ne "0" ] ; do
|
||||
IFACES+=" $1"
|
||||
shift
|
||||
done
|
||||
|
||||
# for now the user must specify interfaces
|
||||
if [ -z "$IFACES" ]; then
|
||||
usage
|
||||
exit 2
|
||||
fi
|
||||
|
||||
notfound()
|
||||
{
|
||||
echo $MYIFACE: not found
|
||||
exit 15
|
||||
}
|
||||
|
||||
# check the interfaces exist
|
||||
for MYIFACE in $IFACES; do
|
||||
grep -q $MYIFACE /proc/net/dev || notfound
|
||||
done
|
||||
|
||||
# support functions
|
||||
|
||||
build_mask()
|
||||
{
|
||||
VEC=$core
|
||||
if [ $VEC -ge 32 ]
|
||||
then
|
||||
MASK_FILL=""
|
||||
MASK_ZERO="00000000"
|
||||
let "IDX = $VEC / 32"
|
||||
for ((i=1; i<=$IDX;i++))
|
||||
do
|
||||
MASK_FILL="${MASK_FILL},${MASK_ZERO}"
|
||||
done
|
||||
|
||||
let "VEC -= 32 * $IDX"
|
||||
MASK_TMP=$((1<<$VEC))
|
||||
MASK=$(printf "%X%s" $MASK_TMP $MASK_FILL)
|
||||
else
|
||||
MASK_TMP=$((1<<$VEC))
|
||||
MASK=$(printf "%X" $MASK_TMP)
|
||||
fi
|
||||
}
|
||||
|
||||
show_affinity()
|
||||
{
|
||||
# returns the MASK variable
|
||||
build_mask
|
||||
|
||||
SMP_I=`sed -E "${NOZEROCOMMA}" /proc/irq/$IRQ/smp_affinity`
|
||||
HINT=`sed -E "${NOZEROCOMMA}" /proc/irq/$IRQ/affinity_hint`
|
||||
printf "ACTUAL %s %d %s <- /proc/irq/$IRQ/smp_affinity\n" $IFACE $core $SMP_I
|
||||
printf "HINT %s %d %s <- /proc/irq/$IRQ/affinity_hint\n" $IFACE $core $HINT
|
||||
IRQ_CHECK=`grep '[-,]' /proc/irq/$IRQ/smp_affinity_list`
|
||||
if [ ! -z $IRQ_CHECK ]; then
|
||||
printf " WARNING -- SMP_AFFINITY is assigned to multiple cores $IRQ_CHECK\n"
|
||||
fi
|
||||
if [ "$SMP_I" != "$HINT" ]; then
|
||||
printf " WARNING -- SMP_AFFINITY VALUE does not match AFFINITY_HINT \n"
|
||||
fi
|
||||
printf "NODE %s %d %s <- /proc/irq/$IRQ/node\n" $IFACE $core `cat /proc/irq/$IRQ/node`
|
||||
printf "LIST %s %d [%s] <- /proc/irq/$IRQ/smp_affinity_list\n" $IFACE $core `cat /proc/irq/$IRQ/smp_affinity_list`
|
||||
printf "XPS %s %d %s <- /sys/class/net/%s/queues/tx-%d/xps_cpus\n" $IFACE $core `cat /sys/class/net/$IFACE/queues/tx-$((n-1))/xps_cpus` $IFACE $((n-1))
|
||||
if [ -z `ls /sys/class/net/$IFACE/queues/tx-$((n-1))/xps_rxqs` ]; then
|
||||
echo "WARNING: xps rxqs not supported on $IFACE"
|
||||
else
|
||||
printf "XPSRXQs %s %d %s <- /sys/class/net/%s/queues/tx-%d/xps_rxqs\n" $IFACE $core `cat /sys/class/net/$IFACE/queues/tx-$((n-1))/xps_rxqs` $IFACE $((n-1))
|
||||
fi
|
||||
printf "TX_MAX %s %d %s <- /sys/class/net/%s/queues/tx-%d/tx_maxrate\n" $IFACE $core `cat /sys/class/net/$IFACE/queues/tx-$((n-1))/tx_maxrate` $IFACE $((n-1))
|
||||
printf "BQLIMIT %s %d %s <- /sys/class/net/%s/queues/tx-%d/byte_queue_limits/limit\n" $IFACE $core `cat /sys/class/net/$IFACE/queues/tx-$((n-1))/byte_queue_limits/limit` $IFACE $((n-1))
|
||||
printf "BQL_MAX %s %d %s <- /sys/class/net/%s/queues/tx-%d/byte_queue_limits/limit_max\n" $IFACE $core `cat /sys/class/net/$IFACE/queues/tx-$((n-1))/byte_queue_limits/limit_max` $IFACE $((n-1))
|
||||
printf "BQL_MIN %s %d %s <- /sys/class/net/%s/queues/tx-%d/byte_queue_limits/limit_min\n" $IFACE $core `cat /sys/class/net/$IFACE/queues/tx-$((n-1))/byte_queue_limits/limit_min` $IFACE $((n-1))
|
||||
if [ -z `ls /sys/class/net/$IFACE/queues/rx-$((n-1))/rps_flow_cnt` ]; then
|
||||
echo "WARNING: aRFS is not supported on $IFACE"
|
||||
else
|
||||
printf "RPSFCNT %s %d %s <- /sys/class/net/%s/queues/rx-%d/rps_flow_cnt\n" $IFACE $core `cat /sys/class/net/$IFACE/queues/rx-$((n-1))/rps_flow_cnt` $IFACE $((n-1))
|
||||
fi
|
||||
if [ -z `ls /sys/class/net/$IFACE/queues/rx-$((n-1))/rps_cpus` ]; then
|
||||
echo "WARNING: rps_cpus is not available on $IFACE"
|
||||
else
|
||||
printf "RPSCPU %s %d %s <- /sys/class/net/%s/queues/rx-%d/rps_cpus\n" $IFACE $core `cat /sys/class/net/$IFACE/queues/rx-$((n-1))/rps_cpus` $IFACE $((n-1))
|
||||
fi
|
||||
echo
|
||||
}
|
||||
|
||||
set_affinity()
|
||||
{
|
||||
# returns the MASK variable
|
||||
build_mask
|
||||
|
||||
printf "%s" $MASK > /proc/irq/$IRQ/smp_affinity
|
||||
printf "%s %d %s -> /proc/irq/$IRQ/smp_affinity\n" $IFACE $core $MASK
|
||||
SMP_I=`sed -E "${NOZEROCOMMA}" /proc/irq/$IRQ/smp_affinity`
|
||||
if [ "$SMP_I" != "$MASK" ]; then
|
||||
printf " ACTUAL\t%s %d %s <- /proc/irq/$IRQ/smp_affinity\n" $IFACE $core $SMP_I
|
||||
printf " WARNING -- SMP_AFFINITY setting failed\n"
|
||||
fi
|
||||
case "$XPS_ENA" in
|
||||
1)
|
||||
printf "%s %d %s -> /sys/class/net/%s/queues/tx-%d/xps_cpus\n" $IFACE $core $MASK $IFACE $((n-1))
|
||||
printf "%s" $MASK > /sys/class/net/$IFACE/queues/tx-$((n-1))/xps_cpus
|
||||
;;
|
||||
2)
|
||||
MASK=0
|
||||
printf "%s %d %s -> /sys/class/net/%s/queues/tx-%d/xps_cpus\n" $IFACE $core $MASK $IFACE $((n-1))
|
||||
printf "%s" $MASK > /sys/class/net/$IFACE/queues/tx-$((n-1))/xps_cpus
|
||||
;;
|
||||
*)
|
||||
esac
|
||||
}
|
||||
|
||||
# Allow usage of , or -
|
||||
#
|
||||
parse_range () {
|
||||
RANGE=${@//,/ }
|
||||
RANGE=${RANGE//-/..}
|
||||
LIST=""
|
||||
for r in $RANGE; do
|
||||
# eval lets us use vars in {#..#} range
|
||||
[[ $r =~ '..' ]] && r="$(eval echo {$r})"
|
||||
LIST+=" $r"
|
||||
done
|
||||
echo $LIST
|
||||
}
|
||||
|
||||
# Affinitize interrupts
|
||||
#
|
||||
doaff()
|
||||
{
|
||||
CORES=$(parse_range $CORES)
|
||||
ncores=$(echo $CORES | wc -w)
|
||||
n=1
|
||||
|
||||
# this script only supports interrupt vectors in pairs,
|
||||
# modification would be required to support a single Tx or Rx queue
|
||||
# per interrupt vector
|
||||
|
||||
queues="${IFACE}-.*TxRx"
|
||||
|
||||
irqs=$(grep "$queues" /proc/interrupts | cut -f1 -d:)
|
||||
[ -z "$irqs" ] && irqs=$(grep $IFACE /proc/interrupts | cut -f1 -d:)
|
||||
[ -z "$irqs" ] && irqs=$(for i in `ls -1 /sys/class/net/${IFACE}/device/msi_irqs | sort -n` ;do grep -w $i: /proc/interrupts | egrep -v 'fdir|async|misc|ctrl' | cut -f 1 -d :; done)
|
||||
[ -z "$irqs" ] && echo "Error: Could not find interrupts for $IFACE"
|
||||
|
||||
if [ "$SHOW" == "1" ] ; then
|
||||
echo "TYPE IFACE CORE MASK -> FILE"
|
||||
echo "============================"
|
||||
else
|
||||
echo "IFACE CORE MASK -> FILE"
|
||||
echo "======================="
|
||||
fi
|
||||
|
||||
for IRQ in $irqs; do
|
||||
[ "$n" -gt "$ncores" ] && n=1
|
||||
j=1
|
||||
# much faster than calling cut for each
|
||||
for i in $CORES; do
|
||||
[ $((j++)) -ge $n ] && break
|
||||
done
|
||||
core=$i
|
||||
if [ "$SHOW" == "1" ] ; then
|
||||
show_affinity
|
||||
else
|
||||
set_affinity
|
||||
fi
|
||||
((n++))
|
||||
done
|
||||
}
|
||||
|
||||
# these next 2 lines would allow script to auto-determine interfaces
|
||||
#[ -z "$IFACES" ] && IFACES=$(ls /sys/class/net)
|
||||
#[ -z "$IFACES" ] && echo "Error: No interfaces up" && exit 1
|
||||
|
||||
# echo IFACES is $IFACES
|
||||
|
||||
CORES=$(</sys/devices/system/cpu/online)
|
||||
[ "$CORES" ] || CORES=$(grep ^proc /proc/cpuinfo | cut -f2 -d:)
|
||||
|
||||
# Core list for each node from sysfs
|
||||
node_dir=/sys/devices/system/node
|
||||
for i in $(ls -d $node_dir/node*); do
|
||||
i=${i/*node/}
|
||||
corelist[$i]=$(<$node_dir/node${i}/cpulist)
|
||||
done
|
||||
|
||||
for IFACE in $IFACES; do
|
||||
# echo $IFACE being modified
|
||||
|
||||
dev_dir=/sys/class/net/$IFACE/device
|
||||
[ -e $dev_dir/numa_node ] && node=$(<$dev_dir/numa_node)
|
||||
[ "$node" ] && [ "$node" -gt 0 ] || node=0
|
||||
|
||||
case "$AFF" in
|
||||
local)
|
||||
CORES=${corelist[$node]}
|
||||
;;
|
||||
remote)
|
||||
[ "$rnode" ] || { [ $node -eq 0 ] && rnode=1 || rnode=0; }
|
||||
CORES=${corelist[$rnode]}
|
||||
;;
|
||||
one)
|
||||
[ -n "$cnt" ] || cnt=0
|
||||
CORES=$cnt
|
||||
;;
|
||||
all)
|
||||
CORES=$CORES
|
||||
;;
|
||||
custom)
|
||||
echo -n "Input cores for $IFACE (ex. 0-7,15-23): "
|
||||
read CORES
|
||||
;;
|
||||
[0-9]*)
|
||||
CORES=$AFF
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# call the worker function
|
||||
doaff
|
||||
done
|
||||
|
||||
# check for irqbalance running
|
||||
IRQBALANCE_ON=`ps ax | grep -v grep | grep -q irqbalance; echo $?`
|
||||
if [ "$IRQBALANCE_ON" == "0" ] ; then
|
||||
echo " WARNING: irqbalance is running and will"
|
||||
echo " likely override this script's affinitization."
|
||||
echo " Please stop the irqbalance service and/or execute"
|
||||
echo " 'killall irqbalance'"
|
||||
exit 2
|
||||
fi
|
56
LingYaoSNIC/HW/kernel/kernel-crete-front-driver/scripts/set_xps_rxqs
Executable file
56
LingYaoSNIC/HW/kernel/kernel-crete-front-driver/scripts/set_xps_rxqs
Executable file
@ -0,0 +1,56 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# Copyright (C) 2019 - 2023 Intel Corporation
|
||||
#
|
||||
# Script to setup mechanism for Tx queue selection based on Rx queue(s) map.
|
||||
# This is done by configuring Rx queue(s) map per Tx queue via sysfs. This
|
||||
# Rx queue(s) map is used during selection of Tx queue in
|
||||
# data path (net/core/dev.c:get_xps_queue).
|
||||
#
|
||||
# typical usage is (as root):
|
||||
# set_xps_rxqs <ethX>
|
||||
#
|
||||
# to get help:
|
||||
# set_xps_rxqs
|
||||
|
||||
iface=$1
|
||||
|
||||
if [ -z "$iface" ]; then
|
||||
echo "Usage: $0 <interface>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CHECK () {
|
||||
"$@"
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error in command ${1}, execution aborted, but some changes may have already been made!" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
CPUMASK () {
|
||||
cpu=$1
|
||||
if [ $cpu -ge 32 ]; then
|
||||
mask_fill=""
|
||||
mask_zero="00000000"
|
||||
let "pow = $cpu / 32"
|
||||
for ((i=1; i<=pow; i++)); do
|
||||
mask_fill="${mask_fill},${mask_zero}"
|
||||
done
|
||||
|
||||
let "cpu -= 32 * $pow"
|
||||
mask_tmp=$((1 << cpu))
|
||||
mask=$(printf "%X%s" $mask_tmp $mask_fill)
|
||||
else
|
||||
mask_tmp=$((1 << cpu))
|
||||
mask=$(printf "%X" $mask_tmp)
|
||||
fi
|
||||
echo $mask
|
||||
}
|
||||
|
||||
for i in /sys/class/net/$iface/queues/tx-*/xps_rxqs; do
|
||||
j=$(echo $i | cut -d'/' -f7 | cut -d'-' -f2)
|
||||
mask=$(CPUMASK $j)
|
||||
echo ${mask} > $i
|
||||
CHECK echo ${mask} > $i
|
||||
done
|
1
LingYaoSNIC/README.md
Normal file
1
LingYaoSNIC/README.md
Normal file
@ -0,0 +1 @@
|
||||
中移自研“灵耀”智能网卡驱动固件
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user