drivers/hsi/clients/ssi_protocol.c

Source file repositories/reference/linux-study-clean/drivers/hsi/clients/ssi_protocol.c

File Facts

System
Linux kernel
Corpus path
drivers/hsi/clients/ssi_protocol.c
Extension
.c
Size
29877 bytes
Lines
1193
Domain
Driver Families
Bucket
drivers/hsi
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 ssip_pn_ops = {
	.ndo_open	= ssip_pn_open,
	.ndo_stop	= ssip_pn_stop,
	.ndo_start_xmit	= ssip_pn_xmit,
};

static void ssip_pn_setup(struct net_device *dev)
{
	static const u8 addr = PN_MEDIA_SOS;

	dev->features		= 0;
	dev->netdev_ops		= &ssip_pn_ops;
	dev->type		= ARPHRD_PHONET;
	dev->flags		= IFF_POINTOPOINT | IFF_NOARP;
	dev->mtu		= SSIP_DEFAULT_MTU;
	dev->hard_header_len	= 1;
	dev->addr_len		= 1;
	dev_addr_set(dev, &addr);
	dev->tx_queue_len	= SSIP_TXQUEUE_LEN;

	dev->needs_free_netdev	= true;
	dev->header_ops		= &phonet_header_ops;
}

static int ssi_protocol_probe(struct device *dev)
{
	static const char ifname[] = "phonet%d";
	struct hsi_client *cl = to_hsi_client(dev);
	struct ssi_protocol *ssi;
	int err;

	ssi = kzalloc_obj(*ssi);
	if (!ssi)
		return -ENOMEM;

	spin_lock_init(&ssi->lock);
	timer_setup(&ssi->rx_wd, ssip_rx_wd, TIMER_DEFERRABLE);
	timer_setup(&ssi->tx_wd, ssip_tx_wd, TIMER_DEFERRABLE);
	timer_setup(&ssi->keep_alive, ssip_keep_alive, 0);
	INIT_LIST_HEAD(&ssi->txqueue);
	INIT_LIST_HEAD(&ssi->cmdqueue);
	atomic_set(&ssi->tx_usecnt, 0);
	hsi_client_set_drvdata(cl, ssi);
	ssi->cl = cl;
	INIT_WORK(&ssi->work, ssip_xmit_work);

	ssi->channel_id_cmd = hsi_get_channel_id_by_name(cl, "mcsaab-control");
	if (ssi->channel_id_cmd < 0) {
		err = ssi->channel_id_cmd;
		dev_err(dev, "Could not get cmd channel (%d)\n", err);
		goto out;
	}

	ssi->channel_id_data = hsi_get_channel_id_by_name(cl, "mcsaab-data");
	if (ssi->channel_id_data < 0) {
		err = ssi->channel_id_data;
		dev_err(dev, "Could not get data channel (%d)\n", err);
		goto out;
	}

	err = ssip_alloc_cmds(ssi);
	if (err < 0) {
		dev_err(dev, "No memory for commands\n");
		goto out;
	}

	ssi->netdev = alloc_netdev(0, ifname, NET_NAME_UNKNOWN, ssip_pn_setup);
	if (!ssi->netdev) {
		dev_err(dev, "No memory for netdev\n");
		err = -ENOMEM;
		goto out1;
	}

	/* MTU range: 6 - 65535 */
	ssi->netdev->min_mtu = PHONET_MIN_MTU;
	ssi->netdev->max_mtu = SSIP_MAX_MTU;

	SET_NETDEV_DEV(ssi->netdev, dev);
	netif_carrier_off(ssi->netdev);
	err = register_netdev(ssi->netdev);
	if (err < 0) {
		dev_err(dev, "Register netdev failed (%d)\n", err);
		goto out2;
	}

	list_add(&ssi->link, &ssip_list);

	dev_dbg(dev, "channel configuration: cmd=%d, data=%d\n",
		ssi->channel_id_cmd, ssi->channel_id_data);

Annotation

Implementation Notes