Lines Matching +full:mctp +full:- +full:controller
1 // SPDX-License-Identifier: GPL-2.0
4 * "DSP0233 Management Component Transport Protocol (MCTP) I3C Transport
17 #include <net/mctp.h>
24 /* 64 byte payload, 4 byte MCTP header */
27 static const int MCTP_I3C_MAXMTU = MCTP_I3C_MAXBUF - 1;
28 /* 4 byte MCTP header, no data, 1 byte PEC */
42 static const char *MCTP_I3C_OF_PROP = "mctp-controller";
64 /* Provisioned ID of our controller */
102 struct i3c_priv_xfer xfer = { .rnw = 1, .len = mi->mrl }; in mctp_i3c_read()
103 struct net_device_stats *stats = &mi->mbus->ndev->stats; in mctp_i3c_read()
110 skb = netdev_alloc_skb(mi->mbus->ndev, in mctp_i3c_read()
111 mi->mrl + sizeof(struct mctp_i3c_internal_hdr)); in mctp_i3c_read()
113 stats->rx_dropped++; in mctp_i3c_read()
114 rc = -ENOMEM; in mctp_i3c_read()
118 skb->protocol = htons(ETH_P_MCTP); in mctp_i3c_read()
122 put_unaligned_be48(mi->pid, ihdr->source); in mctp_i3c_read()
123 put_unaligned_be48(mi->mbus->pid, ihdr->dest); in mctp_i3c_read()
126 xfer.data.in = skb_put(skb, mi->mrl); in mctp_i3c_read()
128 rc = i3c_device_do_priv_xfers(mi->i3c, &xfer, 1); in mctp_i3c_read()
132 if (WARN_ON_ONCE(xfer.len > mi->mrl)) { in mctp_i3c_read()
134 rc = -EIO; in mctp_i3c_read()
138 stats->rx_length_errors++; in mctp_i3c_read()
139 rc = -EIO; in mctp_i3c_read()
144 addr = mi->addr << 1 | 1; in mctp_i3c_read()
146 pec = i2c_smbus_pec(pec, xfer.data.in, xfer.len - 1); in mctp_i3c_read()
147 if (pec != ((u8 *)xfer.data.in)[xfer.len - 1]) { in mctp_i3c_read()
148 stats->rx_crc_errors++; in mctp_i3c_read()
149 rc = -EINVAL; in mctp_i3c_read()
154 skb_trim(skb, xfer.len - 1); in mctp_i3c_read()
157 cb->halen = PID_SIZE; in mctp_i3c_read()
158 put_unaligned_be48(mi->pid, cb->haddr); in mctp_i3c_read()
163 stats->rx_packets++; in mctp_i3c_read()
164 stats->rx_bytes += xfer.len - 1; in mctp_i3c_read()
166 stats->rx_dropped++; in mctp_i3c_read()
183 if (mi->have_mdb) { in mctp_i3c_ibi_handler()
184 if (payload->len > 0) { in mctp_i3c_ibi_handler()
185 if (((u8 *)payload->data)[0] != I3C_MDB_MCTP) { in mctp_i3c_ibi_handler()
186 /* Not a mctp-i3c interrupt, ignore it */ in mctp_i3c_ibi_handler()
210 i3c_device_get_info(mi->i3c, &info); in mctp_i3c_setup()
211 mi->have_mdb = info.bcr & BIT(2); in mctp_i3c_setup()
212 mi->addr = info.dyn_addr; in mctp_i3c_setup()
213 mi->mwl = info.max_write_len; in mctp_i3c_setup()
214 mi->mrl = info.max_read_len; in mctp_i3c_setup()
215 mi->pid = info.pid; in mctp_i3c_setup()
217 rc = i3c_device_request_ibi(mi->i3c, &ibi); in mctp_i3c_setup()
218 if (rc == -ENOTSUPP) { in mctp_i3c_setup()
219 /* This driver only supports In-Band Interrupt mode. in mctp_i3c_setup()
223 dev_warn(i3cdev_to_dev(mi->i3c), in mctp_i3c_setup()
224 "Failed, bus driver doesn't support In-Band Interrupts"); in mctp_i3c_setup()
227 dev_err(i3cdev_to_dev(mi->i3c), in mctp_i3c_setup()
232 rc = i3c_device_enable_ibi(mi->i3c); in mctp_i3c_setup()
237 dev_err(i3cdev_to_dev(mi->i3c), "Failed enabling IBI (%d)\n", rc); in mctp_i3c_setup()
244 i3c_device_free_ibi(mi->i3c); in mctp_i3c_setup()
250 /* Adds a new MCTP i3c_device to a bus */
260 rc = -ENOMEM; in mctp_i3c_add_device()
263 mi->mbus = mbus; in mctp_i3c_add_device()
264 mi->i3c = i3c; in mctp_i3c_add_device()
265 mutex_init(&mi->lock); in mctp_i3c_add_device()
266 list_add(&mi->list, &mbus->devs); in mctp_i3c_add_device()
276 list_del(&mi->list); in mctp_i3c_add_device()
280 dev_warn(i3cdev_to_dev(i3c), "Error adding mctp-i3c device, %d\n", rc); in mctp_i3c_add_device()
291 if (b->bus == i3c->bus) { in mctp_i3c_probe()
298 /* probably no "mctp-controller" property on the i3c bus */ in mctp_i3c_probe()
299 return -ENODEV; in mctp_i3c_probe()
309 mutex_lock(&mi->lock); in mctp_i3c_remove_device()
312 i3c_device_disable_ibi(mi->i3c); in mctp_i3c_remove_device()
313 i3c_device_free_ibi(mi->i3c); in mctp_i3c_remove_device()
316 i3cdev_set_drvdata(mi->i3c, NULL); in mctp_i3c_remove_device()
317 list_del(&mi->list); in mctp_i3c_remove_device()
320 mutex_unlock(&mi->lock); in mctp_i3c_remove_device()
339 /* Returns the device for an address, with mi->lock held */
346 list_for_each_entry(mi, &mbus->devs, list) in mctp_i3c_lookup()
347 if (mi->pid == pid) { in mctp_i3c_lookup()
349 mutex_lock(&mi->lock); in mctp_i3c_lookup()
358 struct net_device_stats *stats = &mbus->ndev->stats; in mctp_i3c_xmit()
369 data_len = skb->len; in mctp_i3c_xmit()
373 pid = get_unaligned_be48(ihdr->dest); in mctp_i3c_xmit()
377 stats->tx_dropped++; in mctp_i3c_xmit()
384 if (data_len + 1 > (unsigned int)mi->mwl) { in mctp_i3c_xmit()
386 stats->tx_dropped++; in mctp_i3c_xmit()
394 data = skb->data; in mctp_i3c_xmit()
397 skb_copy_bits(skb, 0, mbus->tx_scratch, skb->len); in mctp_i3c_xmit()
398 data = mbus->tx_scratch; in mctp_i3c_xmit()
402 addr = mi->addr << 1; in mctp_i3c_xmit()
408 rc = i3c_device_do_priv_xfers(mi->i3c, &xfer, 1); in mctp_i3c_xmit()
410 stats->tx_bytes += data_len; in mctp_i3c_xmit()
411 stats->tx_packets++; in mctp_i3c_xmit()
413 stats->tx_errors++; in mctp_i3c_xmit()
418 mutex_unlock(&mi->lock); in mctp_i3c_xmit()
430 spin_lock_bh(&mbus->tx_lock); in mctp_i3c_tx_thread()
431 skb = mbus->tx_skb; in mctp_i3c_tx_thread()
432 mbus->tx_skb = NULL; in mctp_i3c_tx_thread()
433 spin_unlock_bh(&mbus->tx_lock); in mctp_i3c_tx_thread()
435 if (netif_queue_stopped(mbus->ndev)) in mctp_i3c_tx_thread()
436 netif_wake_queue(mbus->ndev); in mctp_i3c_tx_thread()
442 wait_event_idle(mbus->tx_wq, in mctp_i3c_tx_thread()
443 mbus->tx_skb || kthread_should_stop()); in mctp_i3c_tx_thread()
456 spin_lock(&mbus->tx_lock); in mctp_i3c_start_xmit()
458 if (mbus->tx_skb) { in mctp_i3c_start_xmit()
459 dev_warn_ratelimited(&ndev->dev, "TX with queue stopped"); in mctp_i3c_start_xmit()
462 mbus->tx_skb = skb; in mctp_i3c_start_xmit()
465 spin_unlock(&mbus->tx_lock); in mctp_i3c_start_xmit()
468 wake_up(&mbus->tx_wq); in mctp_i3c_start_xmit()
478 if (mbus->tx_thread) { in mctp_i3c_bus_free()
479 kthread_stop(mbus->tx_thread); in mctp_i3c_bus_free()
480 mbus->tx_thread = NULL; in mctp_i3c_bus_free()
484 list_for_each_entry_safe(mi, tmp, &mbus->devs, list) { in mctp_i3c_bus_free()
488 kfree_skb(mbus->tx_skb); in mctp_i3c_bus_free()
489 list_del(&mbus->list); in mctp_i3c_bus_free()
509 memcpy(ihdr->dest, daddr, PID_SIZE); in mctp_i3c_header_create()
510 memcpy(ihdr->source, saddr, PID_SIZE); in mctp_i3c_header_create()
525 dev->type = ARPHRD_MCTP; in mctp_i3c_net_setup()
527 dev->mtu = MCTP_I3C_MAXMTU; in mctp_i3c_net_setup()
528 dev->min_mtu = MCTP_I3C_MINMTU; in mctp_i3c_net_setup()
529 dev->max_mtu = MCTP_I3C_MAXMTU; in mctp_i3c_net_setup()
530 dev->tx_queue_len = MCTP_I3C_TX_QUEUE_LEN; in mctp_i3c_net_setup()
532 dev->hard_header_len = sizeof(struct mctp_i3c_internal_hdr); in mctp_i3c_net_setup()
533 dev->addr_len = PID_SIZE; in mctp_i3c_net_setup()
535 dev->netdev_ops = &mctp_i3c_ops; in mctp_i3c_net_setup()
536 dev->header_ops = &mctp_i3c_headops; in mctp_i3c_net_setup()
541 struct i3c_dev_desc *master = bus->cur_master; in mctp_i3c_is_mctp_controller()
546 return of_property_read_bool(master->common.master->dev.of_node, in mctp_i3c_is_mctp_controller()
555 master = bus->cur_master; in mctp_i3c_bus_local_pid()
557 return -ENOENT; in mctp_i3c_bus_local_pid()
558 *ret_pid = master->info.pid; in mctp_i3c_bus_local_pid()
574 return ERR_PTR(-ENOENT); in mctp_i3c_bus_add()
576 snprintf(namebuf, sizeof(namebuf), "mctpi3c%d", bus->id); in mctp_i3c_bus_add()
580 rc = -ENOMEM; in mctp_i3c_bus_add()
585 mbus->ndev = ndev; in mctp_i3c_bus_add()
586 mbus->bus = bus; in mctp_i3c_bus_add()
587 INIT_LIST_HEAD(&mbus->devs); in mctp_i3c_bus_add()
588 list_add(&mbus->list, &busdevs); in mctp_i3c_bus_add()
590 rc = mctp_i3c_bus_local_pid(bus, &mbus->pid); in mctp_i3c_bus_add()
592 dev_err(&ndev->dev, "No I3C PID available\n"); in mctp_i3c_bus_add()
595 put_unaligned_be48(mbus->pid, addr); in mctp_i3c_bus_add()
598 init_waitqueue_head(&mbus->tx_wq); in mctp_i3c_bus_add()
599 spin_lock_init(&mbus->tx_lock); in mctp_i3c_bus_add()
600 mbus->tx_thread = kthread_run(mctp_i3c_tx_thread, mbus, in mctp_i3c_bus_add()
601 "%s/tx", ndev->name); in mctp_i3c_bus_add()
602 if (IS_ERR(mbus->tx_thread)) { in mctp_i3c_bus_add()
603 dev_warn(&ndev->dev, "Error creating thread: %pe\n", in mctp_i3c_bus_add()
604 mbus->tx_thread); in mctp_i3c_bus_add()
605 rc = PTR_ERR(mbus->tx_thread); in mctp_i3c_bus_add()
606 mbus->tx_thread = NULL; in mctp_i3c_bus_add()
612 dev_warn(&ndev->dev, "netdev register failed: %d\n", rc); in mctp_i3c_bus_add()
633 /* Unregister calls through to ndo_uninit -> mctp_i3c_bus_free() */ in mctp_i3c_bus_remove()
634 mctp_unregister_netdev(mbus->ndev); in mctp_i3c_bus_remove()
636 free_netdev(mbus->ndev); in mctp_i3c_bus_remove()
640 /* Removes all mctp-i3c busses */
662 if (mbus->bus == bus) in mctp_i3c_bus_add_new()
680 if (mbus->bus == bus) in mctp_i3c_notify_bus_remove()
710 .name = "mctp-i3c",
744 pr_warn("MCTP I3C could not unregister notifier, %d\n", rc); in mctp_i3c_mod_exit()
753 MODULE_DESCRIPTION("MCTP I3C device");