Hi Andrew, On Mon, 2023-07-03 at 16:43 +0200, Andrew Lunn wrote: > > +#define MCTP_I3C_MAXBUF 65536 > > +/* 48 bit Provisioned Id */ > > +#define PID_SIZE 6 > > + > > +/* 64 byte payload, 4 byte MCTP header */ > > +static const int MCTP_I3C_MINMTU = 64 + 4; > > +/* One byte less to allow for the PEC */ > > +static const int MCTP_I3C_MAXMTU = MCTP_I3C_MAXBUF - 1; > > +/* 4 byte MCTP header, no data, 1 byte PEC */ > > +static const int MCTP_I3C_MINLEN = 4 + 1; > > Why static const and not #define? It would also be normal for > variables to be lower case, to make it clear they are in fact > variables, not #defines. My personal preference is for static const since it's less error prone, though had to use #define for the ones used in array sizing. Happy to change to #define if that's the style though. > > +struct mctp_i3c_bus { > > + struct net_device *ndev; > > + > > + struct task_struct *tx_thread; > > + wait_queue_head_t tx_wq; > > + /* tx_lock protects tx_skb and devs */ > > + spinlock_t tx_lock; > > + /* Next skb to transmit */ > > + struct sk_buff *tx_skb; > > + /* Scratch buffer for xmit */ > > + u8 tx_scratch[MCTP_I3C_MAXBUF]; > > + > > + /* Element of busdevs */ > > + struct list_head list; > > + > > + /* Provisioned ID of our controller */ > > + u64 pid; > > + > > + struct i3c_bus *bus; > > + /* Head of mctp_i3c_device.list. Protected by busdevs_lock */ > > + struct list_head devs; > > +}; > > + > > +struct mctp_i3c_device { > > + struct i3c_device *i3c; > > + struct mctp_i3c_bus *mbus; > > + struct list_head list; /* Element of mctp_i3c_bus.devs */ > > + > > + /* Held while tx_thread is using this device */ > > + struct mutex lock; > > + > > + /* Whether BCR indicates MDB is present in IBI */ > > + bool have_mdb; > > + /* I3C dynamic address */ > > + u8 addr; > > + /* Maximum read length */ > > + u16 mrl; > > + /* Maximum write length */ > > + u16 mwl; > > + /* Provisioned ID */ > > + u64 pid; > > +}; > > Since you have commented about most of the members of these > structures, you could use kerneldoc. These aren't intended to be exposed as an API anywhere, just commented for future code readers (including me). Is kerneldoc still appropriate? > > > +/* We synthesise a mac header using the Provisioned ID. > > + * Used to pass dest to mctp_i3c_start_xmit. > > + */ > > +struct mctp_i3c_internal_hdr { > > + u8 dest[PID_SIZE]; > > + u8 source[PID_SIZE]; > > +} __packed; > > + > > +/* Returns the 48 bit Provisioned Id from an i3c_device_info.pid */ > > +static void pid_to_addr(u64 pid, u8 addr[PID_SIZE]) > > +{ > > + pid = cpu_to_be64(pid); > > + memcpy(addr, ((u8 *)&pid) + 2, PID_SIZE); > > +} > > + > > +static u64 addr_to_pid(u8 addr[PID_SIZE]) > > +{ > > + u64 pid = 0; > > + > > + memcpy(((u8 *)&pid) + 2, addr, PID_SIZE); > > + return be64_to_cpu(pid); > > +} > > I don't know anything about MCTP. But Ethernet MAC addresses are also > 48 bits. Could you make use of u64_to_ether_addr() and ether_addr_to_u64()? The 48 bit identifier is an I3C Provisioned ID. It has a similar purpose to an ethernet MAC address but for a different protocol. I think it might cause confusion to code readers if it were passed to ethernet functions. > > > +static int mctp_i3c_setup(struct mctp_i3c_device *mi) > > +{ > > + const struct i3c_ibi_setup ibi = { > > + .max_payload_len = 1, > > + .num_slots = MCTP_I3C_IBI_SLOTS, > > + .handler = mctp_i3c_ibi_handler, > > + }; > > + bool ibi_set = false, ibi_enabled = false; > > + struct i3c_device_info info; > > + int rc; > > + > > + i3c_device_get_info(mi->i3c, &info); > > + mi->have_mdb = info.bcr & BIT(2); > > + mi->addr = info.dyn_addr; > > + mi->mwl = info.max_write_len; > > + mi->mrl = info.max_read_len; > > + mi->pid = info.pid; > > + > > + rc = i3c_device_request_ibi(mi->i3c, &ibi); > > + if (rc == 0) { > > + ibi_set = true; > > + } else if (rc == -ENOTSUPP) { > > In networking, we try to avoid ENOTSUPP and use EOPNOTSUPP: > > https://lore.kernel.org/netdev/20200511165319.2251678-1-kuba@xxxxxxxxxx/ checkpatch noticed this one too, but the existing I3C functions return ENOTSUPP so it needs to match against that. > > +static int mctp_i3c_header_create(struct sk_buff *skb, struct net_device > > *dev, > > + unsigned short type, const void > > *daddr, > > + const void *saddr, unsigned int len) > > +{ > > + struct mctp_i3c_internal_hdr *ihdr; > > + > > + skb_push(skb, sizeof(struct mctp_i3c_internal_hdr)); > > + skb_reset_mac_header(skb); > > + ihdr = (void *)skb_mac_header(skb); > > + memcpy(ihdr->dest, daddr, PID_SIZE); > > + memcpy(ihdr->source, saddr, PID_SIZE); > > ether_addr_copy() ? > > > +/* Returns an ERR_PTR on failure */ > > +static struct mctp_i3c_bus *mctp_i3c_bus_add(struct i3c_bus *bus) > > +__must_hold(&busdevs_lock) > > +{ > > + struct mctp_i3c_bus *mbus = NULL; > > + struct net_device *ndev = NULL; > > + u8 addr[PID_SIZE]; > > + char namebuf[IFNAMSIZ]; > > + int rc; > > + > > + if (!mctp_i3c_is_mctp_controller(bus)) > > + return ERR_PTR(-ENOENT); > > + > > + snprintf(namebuf, sizeof(namebuf), "mctpi3c%d", bus->id); > > + ndev = alloc_netdev(sizeof(*mbus), namebuf, NET_NAME_ENUM, > > mctp_i3c_net_setup); > > + if (!ndev) { > > + pr_warn("No memory for %s\n", namebuf); > > pr_ functions are not liked too much. Is there a struct device you can > use with dev_warn()? I'll change the ones with a device available, that one in particular can be removed anyway. Thanks, Matt