drivers/s390/cio/itcw.c

Source file repositories/reference/linux-study-clean/drivers/s390/cio/itcw.c

File Facts

System
Linux kernel
Corpus path
drivers/s390/cio/itcw.c
Extension
.c
Size
12059 bytes
Lines
373
Domain
Driver Families
Bucket
drivers/s390
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

struct itcw {
	struct tcw *tcw;
	struct tcw *intrg_tcw;
	int num_tidaws;
	int max_tidaws;
	int intrg_num_tidaws;
	int intrg_max_tidaws;
};

/**
 * itcw_get_tcw - return pointer to tcw associated with the itcw
 * @itcw: address of the itcw
 *
 * Return pointer to the tcw associated with the itcw.
 */
struct tcw *itcw_get_tcw(struct itcw *itcw)
{
	return itcw->tcw;
}
EXPORT_SYMBOL(itcw_get_tcw);

/**
 * itcw_calc_size - return the size of an itcw with the given parameters
 * @intrg: if non-zero, add an interrogate tcw
 * @max_tidaws: maximum number of tidaws to be used for data addressing or zero
 * if no tida is to be used.
 * @intrg_max_tidaws: maximum number of tidaws to be used for data addressing
 * by the interrogate tcw, if specified
 *
 * Calculate and return the number of bytes required to hold an itcw with the
 * given parameters and assuming tccbs with maximum size.
 *
 * Note that the resulting size also contains bytes needed for alignment
 * padding as well as padding to ensure that data structures don't cross a
 * 4k-boundary where required.
 */
size_t itcw_calc_size(int intrg, int max_tidaws, int intrg_max_tidaws)
{
	size_t len;
	int cross_count;

	/* Main data. */
	len = sizeof(struct itcw);
	len += /* TCW */ sizeof(struct tcw) + /* TCCB */ TCCB_MAX_SIZE +
	       /* TSB */ sizeof(struct tsb) +
	       /* TIDAL */ max_tidaws * sizeof(struct tidaw);
	/* Interrogate data. */
	if (intrg) {
		len += /* TCW */ sizeof(struct tcw) + /* TCCB */ TCCB_MAX_SIZE +
		       /* TSB */ sizeof(struct tsb) +
		       /* TIDAL */ intrg_max_tidaws * sizeof(struct tidaw);
	}

	/* Maximum required alignment padding. */
	len += /* Initial TCW */ 63 + /* Interrogate TCCB */ 7;

	/* TIDAW lists may not cross a 4k boundary. To cross a
	 * boundary we need to add a TTIC TIDAW. We need to reserve
	 * one additional TIDAW for a TTIC that we may need to add due
	 * to the placement of the data chunk in memory, and a further
	 * TIDAW for each page boundary that the TIDAW list may cross
	 * due to it's own size.
	 */
	if (max_tidaws) {
		cross_count = 1 + ((max_tidaws * sizeof(struct tidaw) - 1)
				   >> PAGE_SHIFT);
		len += cross_count * sizeof(struct tidaw);
	}
	if (intrg_max_tidaws) {
		cross_count = 1 + ((intrg_max_tidaws * sizeof(struct tidaw) - 1)
				   >> PAGE_SHIFT);
		len += cross_count * sizeof(struct tidaw);
	}
	return len;
}
EXPORT_SYMBOL(itcw_calc_size);

#define CROSS4K(x, l)	(((x) & ~4095) != ((x + l) & ~4095))

static inline void *fit_chunk(addr_t *start, addr_t end, size_t len,
			      int align, int check_4k)
{
	addr_t addr;

	addr = ALIGN(*start, align);
	if (check_4k && CROSS4K(addr, len)) {
		addr = ALIGN(addr, 4096);
		addr = ALIGN(addr, align);
	}
	if (addr + len > end)

Annotation

Implementation Notes