drivers/misc/mei/interrupt.c

Source file repositories/reference/linux-study-clean/drivers/misc/mei/interrupt.c

File Facts

System
Linux kernel
Corpus path
drivers/misc/mei/interrupt.c
Extension
.c
Size
16098 bytes
Lines
686
Domain
Driver Families
Bucket
drivers/misc
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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

if (!mei_cl_is_fixed_address(cl)) {
			cl_err(dev, cl, "pending read cb not found\n");
			goto discard;
		}
		cb = mei_cl_alloc_cb(cl, mei_cl_mtu(cl), MEI_FOP_READ, cl->fp);
		if (!cb)
			goto discard;
		list_add_tail(&cb->list, &cl->rd_pending);
	}

	if (mei_hdr->extended) {
		struct mei_ext_hdr *ext = mei_ext_begin(meta);
		do {
			switch (ext->type) {
			case MEI_EXT_HDR_VTAG:
				vtag_hdr = (struct mei_ext_hdr_vtag *)ext;
				break;
			case MEI_EXT_HDR_GSC:
				gsc_f2h = (struct mei_ext_hdr_gsc_f2h *)ext;
				cb->ext_hdr = (struct mei_ext_hdr *) kzalloc_obj(*gsc_f2h);
				if (!cb->ext_hdr) {
					cb->status = -ENOMEM;
					goto discard;
				}
				break;
			case MEI_EXT_HDR_NONE:
				fallthrough;
			default:
				cl_err(dev, cl, "unknown extended header\n");
				cb->status = -EPROTO;
				break;
			}

			ext = mei_ext_next(ext);
		} while (!mei_ext_last(meta, ext));

		if (!vtag_hdr && !gsc_f2h) {
			cl_dbg(dev, cl, "no vtag or gsc found in extended header.\n");
			cb->status = -EPROTO;
			goto discard;
		}
	}

	if (vtag_hdr) {
		cl_dbg(dev, cl, "vtag: %d\n", vtag_hdr->vtag);
		if (cb->vtag && cb->vtag != vtag_hdr->vtag) {
			cl_err(dev, cl, "mismatched tag: %d != %d\n",
			       cb->vtag, vtag_hdr->vtag);
			cb->status = -EPROTO;
			goto discard;
		}
		cb->vtag = vtag_hdr->vtag;
	}

	if (gsc_f2h) {
		u32 ext_hdr_len = mei_ext_hdr_len(&gsc_f2h->hdr);

		if (!dev->hbm_f_gsc_supported) {
			cl_err(dev, cl, "gsc extended header is not supported\n");
			cb->status = -EPROTO;
			goto discard;
		}

		if (length) {
			cl_err(dev, cl, "no data allowed in cb with gsc\n");
			cb->status = -EPROTO;
			goto discard;
		}
		if (ext_hdr_len > sizeof(*gsc_f2h)) {
			cl_err(dev, cl, "gsc extended header is too big %u\n", ext_hdr_len);
			cb->status = -EPROTO;
			goto discard;
		}
		memcpy(cb->ext_hdr, gsc_f2h, ext_hdr_len);
	}

	if (!mei_cl_is_connected(cl)) {
		cl_dbg(dev, cl, "not connected\n");
		cb->status = -ENODEV;
		goto discard;
	}

	if (mei_hdr->dma_ring)
		length = mei_hdr->extension[mei_data2slots(ext_len)];

	buf_sz = length + cb->buf_idx;
	/* catch for integer overflow */
	if (buf_sz < cb->buf_idx) {
		cl_err(dev, cl, "message is too big len %d idx %zu\n",
		       length, cb->buf_idx);

Annotation

Implementation Notes