brintos

brintos / linux-shallow public Read only

0
0
Text · 17.5 KiB · a619a07 Raw
558 lines · c
1/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */2/* Copyright (c) 2015-2018 Mellanox Technologies. All rights reserved */3 4#ifndef _MLXSW_ITEM_H5#define _MLXSW_ITEM_H6 7#include <linux/types.h>8#include <linux/string.h>9#include <linux/bitops.h>10 11struct mlxsw_item {12	unsigned short	offset;		/* bytes in container */13	short		step;		/* step in bytes for indexed items */14	unsigned short	in_step_offset; /* offset within one step */15	unsigned char	shift;		/* shift in bits */16	unsigned char	element_size;	/* size of element in bit array */17	bool		no_real_shift;18	union {19		unsigned char	bits;20		unsigned short	bytes;21	} size;22	const char	*name;23};24 25static inline unsigned int26__mlxsw_item_offset(const struct mlxsw_item *item, unsigned short index,27		    size_t typesize)28{29	BUG_ON(index && !item->step);30	if (item->offset % typesize != 0 ||31	    item->step % typesize != 0 ||32	    item->in_step_offset % typesize != 0) {33		pr_err("mlxsw: item bug (name=%s,offset=%x,step=%x,in_step_offset=%x,typesize=%zx)\n",34		       item->name, item->offset, item->step,35		       item->in_step_offset, typesize);36		BUG();37	}38 39	return ((item->offset + item->step * index + item->in_step_offset) /40		typesize);41}42 43static inline u8 __mlxsw_item_get8(const char *buf,44				   const struct mlxsw_item *item,45				   unsigned short index)46{47	unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u8));48	u8 *b = (u8 *) buf;49	u8 tmp;50 51	tmp = b[offset];52	tmp >>= item->shift;53	tmp &= GENMASK(item->size.bits - 1, 0);54	if (item->no_real_shift)55		tmp <<= item->shift;56	return tmp;57}58 59static inline void __mlxsw_item_set8(char *buf, const struct mlxsw_item *item,60				     unsigned short index, u8 val)61{62	unsigned int offset = __mlxsw_item_offset(item, index,63						  sizeof(u8));64	u8 *b = (u8 *) buf;65	u8 mask = GENMASK(item->size.bits - 1, 0) << item->shift;66	u8 tmp;67 68	if (!item->no_real_shift)69		val <<= item->shift;70	val &= mask;71	tmp = b[offset];72	tmp &= ~mask;73	tmp |= val;74	b[offset] = tmp;75}76 77static inline u16 __mlxsw_item_get16(const char *buf,78				     const struct mlxsw_item *item,79				     unsigned short index)80{81	unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u16));82	__be16 *b = (__be16 *) buf;83	u16 tmp;84 85	tmp = be16_to_cpu(b[offset]);86	tmp >>= item->shift;87	tmp &= GENMASK(item->size.bits - 1, 0);88	if (item->no_real_shift)89		tmp <<= item->shift;90	return tmp;91}92 93static inline void __mlxsw_item_set16(char *buf, const struct mlxsw_item *item,94				      unsigned short index, u16 val)95{96	unsigned int offset = __mlxsw_item_offset(item, index,97						  sizeof(u16));98	__be16 *b = (__be16 *) buf;99	u16 mask = GENMASK(item->size.bits - 1, 0) << item->shift;100	u16 tmp;101 102	if (!item->no_real_shift)103		val <<= item->shift;104	val &= mask;105	tmp = be16_to_cpu(b[offset]);106	tmp &= ~mask;107	tmp |= val;108	b[offset] = cpu_to_be16(tmp);109}110 111static inline u32 __mlxsw_item_get32(const char *buf,112				     const struct mlxsw_item *item,113				     unsigned short index)114{115	unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u32));116	__be32 *b = (__be32 *) buf;117	u32 tmp;118 119	tmp = be32_to_cpu(b[offset]);120	tmp >>= item->shift;121	tmp &= GENMASK(item->size.bits - 1, 0);122	if (item->no_real_shift)123		tmp <<= item->shift;124	return tmp;125}126 127static inline void __mlxsw_item_set32(char *buf, const struct mlxsw_item *item,128				      unsigned short index, u32 val)129{130	unsigned int offset = __mlxsw_item_offset(item, index,131						  sizeof(u32));132	__be32 *b = (__be32 *) buf;133	u32 mask = GENMASK(item->size.bits - 1, 0) << item->shift;134	u32 tmp;135 136	if (!item->no_real_shift)137		val <<= item->shift;138	val &= mask;139	tmp = be32_to_cpu(b[offset]);140	tmp &= ~mask;141	tmp |= val;142	b[offset] = cpu_to_be32(tmp);143}144 145static inline u64 __mlxsw_item_get64(const char *buf,146				     const struct mlxsw_item *item,147				     unsigned short index)148{149	unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u64));150	__be64 *b = (__be64 *) buf;151	u64 tmp;152 153	tmp = be64_to_cpu(b[offset]);154	tmp >>= item->shift;155	tmp &= GENMASK_ULL(item->size.bits - 1, 0);156	if (item->no_real_shift)157		tmp <<= item->shift;158	return tmp;159}160 161static inline void __mlxsw_item_set64(char *buf, const struct mlxsw_item *item,162				      unsigned short index, u64 val)163{164	unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u64));165	__be64 *b = (__be64 *) buf;166	u64 mask = GENMASK_ULL(item->size.bits - 1, 0) << item->shift;167	u64 tmp;168 169	if (!item->no_real_shift)170		val <<= item->shift;171	val &= mask;172	tmp = be64_to_cpu(b[offset]);173	tmp &= ~mask;174	tmp |= val;175	b[offset] = cpu_to_be64(tmp);176}177 178static inline void __mlxsw_item_memcpy_from(const char *buf, char *dst,179					    const struct mlxsw_item *item,180					    unsigned short index)181{182	unsigned int offset = __mlxsw_item_offset(item, index, sizeof(char));183 184	memcpy(dst, &buf[offset], item->size.bytes);185}186 187static inline void __mlxsw_item_memcpy_to(char *buf, const char *src,188					  const struct mlxsw_item *item,189					  unsigned short index)190{191	unsigned int offset = __mlxsw_item_offset(item, index, sizeof(char));192 193	memcpy(&buf[offset], src, item->size.bytes);194}195 196static inline char *__mlxsw_item_data(char *buf, const struct mlxsw_item *item,197				      unsigned short index)198{199	unsigned int offset = __mlxsw_item_offset(item, index, sizeof(char));200 201	return &buf[offset];202}203 204static inline u16205__mlxsw_item_bit_array_offset(const struct mlxsw_item *item,206			      u16 index, u8 *shift)207{208	u16 max_index, be_index;209	u16 offset;		/* byte offset inside the array */210	u8 in_byte_index;211 212	BUG_ON(index && !item->element_size);213	if (item->offset % sizeof(u32) != 0 ||214	    BITS_PER_BYTE % item->element_size != 0) {215		pr_err("mlxsw: item bug (name=%s,offset=%x,element_size=%x)\n",216		       item->name, item->offset, item->element_size);217		BUG();218	}219 220	max_index = (item->size.bytes << 3) / item->element_size - 1;221	if (WARN_ONCE(index > max_index,222		      "name=%s,index=%u,max_index=%u\n", item->name, index,223		      max_index))224		index = 0;225	be_index = max_index - index;226	offset = be_index * item->element_size >> 3;227	in_byte_index  = index % (BITS_PER_BYTE / item->element_size);228	*shift = in_byte_index * item->element_size;229 230	return item->offset + offset;231}232 233static inline u8 __mlxsw_item_bit_array_get(const char *buf,234					    const struct mlxsw_item *item,235					    u16 index)236{237	u8 shift, tmp;238	u16 offset = __mlxsw_item_bit_array_offset(item, index, &shift);239 240	tmp = buf[offset];241	tmp >>= shift;242	tmp &= GENMASK(item->element_size - 1, 0);243	return tmp;244}245 246static inline void __mlxsw_item_bit_array_set(char *buf,247					      const struct mlxsw_item *item,248					      u16 index, u8 val)249{250	u8 shift, tmp;251	u16 offset = __mlxsw_item_bit_array_offset(item, index, &shift);252	u8 mask = GENMASK(item->element_size - 1, 0) << shift;253 254	val <<= shift;255	val &= mask;256	tmp = buf[offset];257	tmp &= ~mask;258	tmp |= val;259	buf[offset] = tmp;260}261 262#define __ITEM_NAME(_type, _cname, _iname)					\263	mlxsw_##_type##_##_cname##_##_iname##_item264 265/* _type: cmd_mbox, reg, etc.266 * _cname: containter name (e.g. command name, register name)267 * _iname: item name within the container268 */269 270#define MLXSW_ITEM8(_type, _cname, _iname, _offset, _shift, _sizebits)		\271static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {			\272	.offset = _offset,							\273	.shift = _shift,							\274	.size = {.bits = _sizebits,},						\275	.name = #_type "_" #_cname "_" #_iname,					\276};										\277static inline u8 __maybe_unused							\278mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf)			\279{										\280	return __mlxsw_item_get8(buf, &__ITEM_NAME(_type, _cname, _iname), 0);	\281}										\282static inline void __maybe_unused						\283mlxsw_##_type##_##_cname##_##_iname##_set(char *buf, u8 val)			\284{										\285	__mlxsw_item_set8(buf, &__ITEM_NAME(_type, _cname, _iname), 0, val);	\286}287 288#define MLXSW_ITEM8_INDEXED(_type, _cname, _iname, _offset, _shift, _sizebits,	\289			    _step, _instepoffset, _norealshift)			\290static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {			\291	.offset = _offset,							\292	.step = _step,								\293	.in_step_offset = _instepoffset,					\294	.shift = _shift,							\295	.no_real_shift = _norealshift,						\296	.size = {.bits = _sizebits,},						\297	.name = #_type "_" #_cname "_" #_iname,					\298};										\299static inline u8 __maybe_unused							\300mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf, unsigned short index)\301{										\302	return __mlxsw_item_get8(buf, &__ITEM_NAME(_type, _cname, _iname),	\303				 index);					\304}										\305static inline void __maybe_unused						\306mlxsw_##_type##_##_cname##_##_iname##_set(char *buf, unsigned short index,	\307					  u8 val)				\308{										\309	__mlxsw_item_set8(buf, &__ITEM_NAME(_type, _cname, _iname),		\310			  index, val);						\311}312 313#define MLXSW_ITEM16(_type, _cname, _iname, _offset, _shift, _sizebits)		\314static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {			\315	.offset = _offset,							\316	.shift = _shift,							\317	.size = {.bits = _sizebits,},						\318	.name = #_type "_" #_cname "_" #_iname,					\319};										\320static inline u16 __maybe_unused						\321mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf)			\322{										\323	return __mlxsw_item_get16(buf, &__ITEM_NAME(_type, _cname, _iname), 0);	\324}										\325static inline void __maybe_unused						\326mlxsw_##_type##_##_cname##_##_iname##_set(char *buf, u16 val)			\327{										\328	__mlxsw_item_set16(buf, &__ITEM_NAME(_type, _cname, _iname), 0, val);	\329}330 331#define MLXSW_ITEM16_INDEXED(_type, _cname, _iname, _offset, _shift, _sizebits,	\332			     _step, _instepoffset, _norealshift)		\333static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {			\334	.offset = _offset,							\335	.step = _step,								\336	.in_step_offset = _instepoffset,					\337	.shift = _shift,							\338	.no_real_shift = _norealshift,						\339	.size = {.bits = _sizebits,},						\340	.name = #_type "_" #_cname "_" #_iname,					\341};										\342static inline u16 __maybe_unused						\343mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf, unsigned short index)\344{										\345	return __mlxsw_item_get16(buf, &__ITEM_NAME(_type, _cname, _iname),	\346				  index);					\347}										\348static inline void __maybe_unused						\349mlxsw_##_type##_##_cname##_##_iname##_set(char *buf, unsigned short index,	\350					  u16 val)				\351{										\352	__mlxsw_item_set16(buf, &__ITEM_NAME(_type, _cname, _iname),		\353			   index, val);						\354}355 356#define MLXSW_ITEM32(_type, _cname, _iname, _offset, _shift, _sizebits)		\357static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {			\358	.offset = _offset,							\359	.shift = _shift,							\360	.size = {.bits = _sizebits,},						\361	.name = #_type "_" #_cname "_" #_iname,					\362};										\363static inline u32 __maybe_unused						\364mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf)			\365{										\366	return __mlxsw_item_get32(buf, &__ITEM_NAME(_type, _cname, _iname), 0);	\367}										\368static inline void __maybe_unused						\369mlxsw_##_type##_##_cname##_##_iname##_set(char *buf, u32 val)			\370{										\371	__mlxsw_item_set32(buf, &__ITEM_NAME(_type, _cname, _iname), 0, val);	\372}373 374#define LOCAL_PORT_LSB_SIZE 8375#define LOCAL_PORT_MSB_SIZE 2376 377#define MLXSW_ITEM32_LP(_type, _cname, _offset1, _shift1, _offset2, _shift2)	\378static struct mlxsw_item __ITEM_NAME(_type, _cname, local_port) = {		\379	.offset = _offset1,							\380	.shift = _shift1,							\381	.size = {.bits = LOCAL_PORT_LSB_SIZE,},					\382	.name = #_type "_" #_cname "_local_port",				\383};										\384static struct mlxsw_item __ITEM_NAME(_type, _cname, lp_msb) = {			\385	.offset = _offset2,							\386	.shift = _shift2,							\387	.size = {.bits = LOCAL_PORT_MSB_SIZE,},					\388	.name = #_type "_" #_cname "_lp_msb",					\389};										\390static inline u32 __maybe_unused						\391mlxsw_##_type##_##_cname##_local_port_get(const char *buf)			\392{										\393	u32 local_port, lp_msb;							\394										\395	local_port = __mlxsw_item_get32(buf, &__ITEM_NAME(_type, _cname,	\396					local_port), 0);			\397	lp_msb = __mlxsw_item_get32(buf, &__ITEM_NAME(_type, _cname, lp_msb),	\398				   0);						\399	return (lp_msb << LOCAL_PORT_LSB_SIZE) + local_port;			\400}										\401static inline void __maybe_unused						\402mlxsw_##_type##_##_cname##_local_port_set(char *buf, u32 val)			\403{										\404	__mlxsw_item_set32(buf, &__ITEM_NAME(_type, _cname, local_port), 0,	\405			   val & ((1 << LOCAL_PORT_LSB_SIZE) - 1));		\406	__mlxsw_item_set32(buf, &__ITEM_NAME(_type, _cname, lp_msb), 0,		\407			   val >> LOCAL_PORT_LSB_SIZE);				\408}409 410#define MLXSW_ITEM32_INDEXED(_type, _cname, _iname, _offset, _shift, _sizebits,	\411			     _step, _instepoffset, _norealshift)		\412static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {			\413	.offset = _offset,							\414	.step = _step,								\415	.in_step_offset = _instepoffset,					\416	.shift = _shift,							\417	.no_real_shift = _norealshift,						\418	.size = {.bits = _sizebits,},						\419	.name = #_type "_" #_cname "_" #_iname,					\420};										\421static inline u32 __maybe_unused						\422mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf, unsigned short index)\423{										\424	return __mlxsw_item_get32(buf, &__ITEM_NAME(_type, _cname, _iname),	\425				  index);					\426}										\427static inline void __maybe_unused						\428mlxsw_##_type##_##_cname##_##_iname##_set(char *buf, unsigned short index,	\429					  u32 val)				\430{										\431	__mlxsw_item_set32(buf, &__ITEM_NAME(_type, _cname, _iname),		\432			   index, val);						\433}434 435#define MLXSW_ITEM64(_type, _cname, _iname, _offset, _shift, _sizebits)		\436static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {			\437	.offset = _offset,							\438	.shift = _shift,							\439	.size = {.bits = _sizebits,},						\440	.name = #_type "_" #_cname "_" #_iname,					\441};										\442static inline u64 __maybe_unused						\443mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf)			\444{										\445	return __mlxsw_item_get64(buf, &__ITEM_NAME(_type, _cname, _iname), 0);	\446}										\447static inline void __maybe_unused						\448mlxsw_##_type##_##_cname##_##_iname##_set(char *buf, u64 val)			\449{										\450	__mlxsw_item_set64(buf, &__ITEM_NAME(_type, _cname, _iname), 0,	val);	\451}452 453#define MLXSW_ITEM64_INDEXED(_type, _cname, _iname, _offset, _shift,		\454			     _sizebits, _step, _instepoffset, _norealshift)	\455static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {			\456	.offset = _offset,							\457	.step = _step,								\458	.in_step_offset = _instepoffset,					\459	.shift = _shift,							\460	.no_real_shift = _norealshift,						\461	.size = {.bits = _sizebits,},						\462	.name = #_type "_" #_cname "_" #_iname,					\463};										\464static inline u64 __maybe_unused						\465mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf, unsigned short index)\466{										\467	return __mlxsw_item_get64(buf, &__ITEM_NAME(_type, _cname, _iname),	\468				  index);					\469}										\470static inline void __maybe_unused						\471mlxsw_##_type##_##_cname##_##_iname##_set(char *buf, unsigned short index,	\472					  u64 val)				\473{										\474	__mlxsw_item_set64(buf, &__ITEM_NAME(_type, _cname, _iname),		\475			   index, val);						\476}477 478#define MLXSW_ITEM_BUF(_type, _cname, _iname, _offset, _sizebytes)		\479static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {			\480	.offset = _offset,							\481	.size = {.bytes = _sizebytes,},						\482	.name = #_type "_" #_cname "_" #_iname,					\483};										\484static inline void __maybe_unused						\485mlxsw_##_type##_##_cname##_##_iname##_memcpy_from(const char *buf, char *dst)	\486{										\487	__mlxsw_item_memcpy_from(buf, dst,					\488				 &__ITEM_NAME(_type, _cname, _iname), 0);	\489}										\490static inline void __maybe_unused						\491mlxsw_##_type##_##_cname##_##_iname##_memcpy_to(char *buf, const char *src)	\492{										\493	__mlxsw_item_memcpy_to(buf, src,					\494			       &__ITEM_NAME(_type, _cname, _iname), 0);		\495}										\496static inline char * __maybe_unused						\497mlxsw_##_type##_##_cname##_##_iname##_data(char *buf)				\498{										\499	return __mlxsw_item_data(buf, &__ITEM_NAME(_type, _cname, _iname), 0);	\500}501 502#define MLXSW_ITEM_BUF_INDEXED(_type, _cname, _iname, _offset, _sizebytes,	\503			       _step, _instepoffset)				\504static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {			\505	.offset = _offset,							\506	.step = _step,								\507	.in_step_offset = _instepoffset,					\508	.size = {.bytes = _sizebytes,},						\509	.name = #_type "_" #_cname "_" #_iname,					\510};										\511static inline void __maybe_unused						\512mlxsw_##_type##_##_cname##_##_iname##_memcpy_from(const char *buf,		\513						  unsigned short index,		\514						  char *dst)			\515{										\516	__mlxsw_item_memcpy_from(buf, dst,					\517				 &__ITEM_NAME(_type, _cname, _iname), index);	\518}										\519static inline void __maybe_unused						\520mlxsw_##_type##_##_cname##_##_iname##_memcpy_to(char *buf,			\521						unsigned short index,		\522						const char *src)		\523{										\524	__mlxsw_item_memcpy_to(buf, src,					\525			       &__ITEM_NAME(_type, _cname, _iname), index);	\526}										\527static inline char * __maybe_unused						\528mlxsw_##_type##_##_cname##_##_iname##_data(char *buf, unsigned short index)	\529{										\530	return __mlxsw_item_data(buf,						\531				 &__ITEM_NAME(_type, _cname, _iname), index);	\532}533 534#define MLXSW_ITEM_BIT_ARRAY(_type, _cname, _iname, _offset, _sizebytes,	\535			     _element_size)					\536static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = {			\537	.offset = _offset,							\538	.element_size = _element_size,						\539	.size = {.bytes = _sizebytes,},						\540	.name = #_type "_" #_cname "_" #_iname,					\541};										\542static inline u8 __maybe_unused							\543mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf, u16 index)		\544{										\545	return __mlxsw_item_bit_array_get(buf,					\546					  &__ITEM_NAME(_type, _cname, _iname),	\547					  index);				\548}										\549static inline void __maybe_unused						\550mlxsw_##_type##_##_cname##_##_iname##_set(char *buf, u16 index, u8 val)		\551{										\552	return __mlxsw_item_bit_array_set(buf,					\553					  &__ITEM_NAME(_type, _cname, _iname),	\554					  index, val);				\555}										\556 557#endif558