drivers/net/can/kvaser_pciefd/kvaser_pciefd_core.c

Source file repositories/reference/linux-study-clean/drivers/net/can/kvaser_pciefd/kvaser_pciefd_core.c

File Facts

System
Linux kernel
Corpus path
drivers/net/can/kvaser_pciefd/kvaser_pciefd_core.c
Extension
.c
Size
57987 bytes
Lines
1909
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct net_device_ops kvaser_pciefd_netdev_ops = {
	.ndo_open = kvaser_pciefd_open,
	.ndo_stop = kvaser_pciefd_stop,
	.ndo_start_xmit = kvaser_pciefd_start_xmit,
	.ndo_hwtstamp_get = can_hwtstamp_get,
	.ndo_hwtstamp_set = can_hwtstamp_set,
};

static int kvaser_pciefd_set_phys_id(struct net_device *netdev,
				     enum ethtool_phys_id_state state)
{
	struct kvaser_pciefd_can *can = netdev_priv(netdev);

	switch (state) {
	case ETHTOOL_ID_ACTIVE:
		return 3; /* 3 On/Off cycles per second */

	case ETHTOOL_ID_ON:
		kvaser_pciefd_set_led(can, true);
		return 0;

	case ETHTOOL_ID_OFF:
	case ETHTOOL_ID_INACTIVE:
		kvaser_pciefd_set_led(can, false);
		return 0;

	default:
		return -EINVAL;
	}
}

static const struct ethtool_ops kvaser_pciefd_ethtool_ops = {
	.get_ts_info = can_ethtool_op_get_ts_info_hwts,
	.set_phys_id = kvaser_pciefd_set_phys_id,
};

static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie)
{
	int i;

	for (i = 0; i < pcie->nr_channels; i++) {
		struct net_device *netdev;
		struct kvaser_pciefd_can *can;
		u32 status, tx_nr_packets_max;
		int ret;

		netdev = alloc_candev(sizeof(struct kvaser_pciefd_can),
				      roundup_pow_of_two(KVASER_PCIEFD_CAN_TX_MAX_COUNT));
		if (!netdev)
			return -ENOMEM;

		can = netdev_priv(netdev);
		netdev->netdev_ops = &kvaser_pciefd_netdev_ops;
		netdev->ethtool_ops = &kvaser_pciefd_ethtool_ops;
		can->reg_base = KVASER_PCIEFD_KCAN_CHX_ADDR(pcie, i);
		can->kv_pcie = pcie;
		can->cmd_seq = 0;
		can->err_rep_cnt = 0;
		can->completed_tx_pkts = 0;
		can->completed_tx_bytes = 0;
		can->bec.txerr = 0;
		can->bec.rxerr = 0;
		can->can.dev->dev_port = i;

		init_completion(&can->start_comp);
		init_completion(&can->flush_comp);
		timer_setup(&can->bec_poll_timer, kvaser_pciefd_bec_poll_timer, 0);

		/* Disable Bus load reporting */
		iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_BUS_LOAD_REG);

		can->ioc = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_IOC_REG);
		kvaser_pciefd_set_led(can, false);

		tx_nr_packets_max =
			FIELD_GET(KVASER_PCIEFD_KCAN_TX_NR_PACKETS_MAX_MASK,
				  ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG));
		can->tx_max_count = min(KVASER_PCIEFD_CAN_TX_MAX_COUNT, tx_nr_packets_max - 1);

		can->can.clock.freq = pcie->freq;
		spin_lock_init(&can->lock);

		can->can.bittiming_const = &kvaser_pciefd_bittiming_const;
		can->can.fd.data_bittiming_const = &kvaser_pciefd_bittiming_const;
		can->can.do_set_bittiming = kvaser_pciefd_set_nominal_bittiming;
		can->can.fd.do_set_data_bittiming = kvaser_pciefd_set_data_bittiming;
		can->can.do_set_mode = kvaser_pciefd_set_mode;
		can->can.do_get_berr_counter = kvaser_pciefd_get_berr_counter;
		can->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY |
					      CAN_CTRLMODE_FD |

Annotation

Implementation Notes