162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci#include <linux/kernel.h> 462306a36Sopenharmony_ci#include <linux/irqflags.h> 562306a36Sopenharmony_ci#include <linux/string.h> 662306a36Sopenharmony_ci#include <linux/errno.h> 762306a36Sopenharmony_ci#include <linux/bug.h> 862306a36Sopenharmony_ci#include "printk_ringbuffer.h" 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci/** 1162306a36Sopenharmony_ci * DOC: printk_ringbuffer overview 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * Data Structure 1462306a36Sopenharmony_ci * -------------- 1562306a36Sopenharmony_ci * The printk_ringbuffer is made up of 3 internal ringbuffers: 1662306a36Sopenharmony_ci * 1762306a36Sopenharmony_ci * desc_ring 1862306a36Sopenharmony_ci * A ring of descriptors and their meta data (such as sequence number, 1962306a36Sopenharmony_ci * timestamp, loglevel, etc.) as well as internal state information about 2062306a36Sopenharmony_ci * the record and logical positions specifying where in the other 2162306a36Sopenharmony_ci * ringbuffer the text strings are located. 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * text_data_ring 2462306a36Sopenharmony_ci * A ring of data blocks. A data block consists of an unsigned long 2562306a36Sopenharmony_ci * integer (ID) that maps to a desc_ring index followed by the text 2662306a36Sopenharmony_ci * string of the record. 2762306a36Sopenharmony_ci * 2862306a36Sopenharmony_ci * The internal state information of a descriptor is the key element to allow 2962306a36Sopenharmony_ci * readers and writers to locklessly synchronize access to the data. 3062306a36Sopenharmony_ci * 3162306a36Sopenharmony_ci * Implementation 3262306a36Sopenharmony_ci * -------------- 3362306a36Sopenharmony_ci * 3462306a36Sopenharmony_ci * Descriptor Ring 3562306a36Sopenharmony_ci * ~~~~~~~~~~~~~~~ 3662306a36Sopenharmony_ci * The descriptor ring is an array of descriptors. A descriptor contains 3762306a36Sopenharmony_ci * essential meta data to track the data of a printk record using 3862306a36Sopenharmony_ci * blk_lpos structs pointing to associated text data blocks (see 3962306a36Sopenharmony_ci * "Data Rings" below). Each descriptor is assigned an ID that maps 4062306a36Sopenharmony_ci * directly to index values of the descriptor array and has a state. The ID 4162306a36Sopenharmony_ci * and the state are bitwise combined into a single descriptor field named 4262306a36Sopenharmony_ci * @state_var, allowing ID and state to be synchronously and atomically 4362306a36Sopenharmony_ci * updated. 4462306a36Sopenharmony_ci * 4562306a36Sopenharmony_ci * Descriptors have four states: 4662306a36Sopenharmony_ci * 4762306a36Sopenharmony_ci * reserved 4862306a36Sopenharmony_ci * A writer is modifying the record. 4962306a36Sopenharmony_ci * 5062306a36Sopenharmony_ci * committed 5162306a36Sopenharmony_ci * The record and all its data are written. A writer can reopen the 5262306a36Sopenharmony_ci * descriptor (transitioning it back to reserved), but in the committed 5362306a36Sopenharmony_ci * state the data is consistent. 5462306a36Sopenharmony_ci * 5562306a36Sopenharmony_ci * finalized 5662306a36Sopenharmony_ci * The record and all its data are complete and available for reading. A 5762306a36Sopenharmony_ci * writer cannot reopen the descriptor. 5862306a36Sopenharmony_ci * 5962306a36Sopenharmony_ci * reusable 6062306a36Sopenharmony_ci * The record exists, but its text and/or meta data may no longer be 6162306a36Sopenharmony_ci * available. 6262306a36Sopenharmony_ci * 6362306a36Sopenharmony_ci * Querying the @state_var of a record requires providing the ID of the 6462306a36Sopenharmony_ci * descriptor to query. This can yield a possible fifth (pseudo) state: 6562306a36Sopenharmony_ci * 6662306a36Sopenharmony_ci * miss 6762306a36Sopenharmony_ci * The descriptor being queried has an unexpected ID. 6862306a36Sopenharmony_ci * 6962306a36Sopenharmony_ci * The descriptor ring has a @tail_id that contains the ID of the oldest 7062306a36Sopenharmony_ci * descriptor and @head_id that contains the ID of the newest descriptor. 7162306a36Sopenharmony_ci * 7262306a36Sopenharmony_ci * When a new descriptor should be created (and the ring is full), the tail 7362306a36Sopenharmony_ci * descriptor is invalidated by first transitioning to the reusable state and 7462306a36Sopenharmony_ci * then invalidating all tail data blocks up to and including the data blocks 7562306a36Sopenharmony_ci * associated with the tail descriptor (for the text ring). Then 7662306a36Sopenharmony_ci * @tail_id is advanced, followed by advancing @head_id. And finally the 7762306a36Sopenharmony_ci * @state_var of the new descriptor is initialized to the new ID and reserved 7862306a36Sopenharmony_ci * state. 7962306a36Sopenharmony_ci * 8062306a36Sopenharmony_ci * The @tail_id can only be advanced if the new @tail_id would be in the 8162306a36Sopenharmony_ci * committed or reusable queried state. This makes it possible that a valid 8262306a36Sopenharmony_ci * sequence number of the tail is always available. 8362306a36Sopenharmony_ci * 8462306a36Sopenharmony_ci * Descriptor Finalization 8562306a36Sopenharmony_ci * ~~~~~~~~~~~~~~~~~~~~~~~ 8662306a36Sopenharmony_ci * When a writer calls the commit function prb_commit(), record data is 8762306a36Sopenharmony_ci * fully stored and is consistent within the ringbuffer. However, a writer can 8862306a36Sopenharmony_ci * reopen that record, claiming exclusive access (as with prb_reserve()), and 8962306a36Sopenharmony_ci * modify that record. When finished, the writer must again commit the record. 9062306a36Sopenharmony_ci * 9162306a36Sopenharmony_ci * In order for a record to be made available to readers (and also become 9262306a36Sopenharmony_ci * recyclable for writers), it must be finalized. A finalized record cannot be 9362306a36Sopenharmony_ci * reopened and can never become "unfinalized". Record finalization can occur 9462306a36Sopenharmony_ci * in three different scenarios: 9562306a36Sopenharmony_ci * 9662306a36Sopenharmony_ci * 1) A writer can simultaneously commit and finalize its record by calling 9762306a36Sopenharmony_ci * prb_final_commit() instead of prb_commit(). 9862306a36Sopenharmony_ci * 9962306a36Sopenharmony_ci * 2) When a new record is reserved and the previous record has been 10062306a36Sopenharmony_ci * committed via prb_commit(), that previous record is automatically 10162306a36Sopenharmony_ci * finalized. 10262306a36Sopenharmony_ci * 10362306a36Sopenharmony_ci * 3) When a record is committed via prb_commit() and a newer record 10462306a36Sopenharmony_ci * already exists, the record being committed is automatically finalized. 10562306a36Sopenharmony_ci * 10662306a36Sopenharmony_ci * Data Ring 10762306a36Sopenharmony_ci * ~~~~~~~~~ 10862306a36Sopenharmony_ci * The text data ring is a byte array composed of data blocks. Data blocks are 10962306a36Sopenharmony_ci * referenced by blk_lpos structs that point to the logical position of the 11062306a36Sopenharmony_ci * beginning of a data block and the beginning of the next adjacent data 11162306a36Sopenharmony_ci * block. Logical positions are mapped directly to index values of the byte 11262306a36Sopenharmony_ci * array ringbuffer. 11362306a36Sopenharmony_ci * 11462306a36Sopenharmony_ci * Each data block consists of an ID followed by the writer data. The ID is 11562306a36Sopenharmony_ci * the identifier of a descriptor that is associated with the data block. A 11662306a36Sopenharmony_ci * given data block is considered valid if all of the following conditions 11762306a36Sopenharmony_ci * are met: 11862306a36Sopenharmony_ci * 11962306a36Sopenharmony_ci * 1) The descriptor associated with the data block is in the committed 12062306a36Sopenharmony_ci * or finalized queried state. 12162306a36Sopenharmony_ci * 12262306a36Sopenharmony_ci * 2) The blk_lpos struct within the descriptor associated with the data 12362306a36Sopenharmony_ci * block references back to the same data block. 12462306a36Sopenharmony_ci * 12562306a36Sopenharmony_ci * 3) The data block is within the head/tail logical position range. 12662306a36Sopenharmony_ci * 12762306a36Sopenharmony_ci * If the writer data of a data block would extend beyond the end of the 12862306a36Sopenharmony_ci * byte array, only the ID of the data block is stored at the logical 12962306a36Sopenharmony_ci * position and the full data block (ID and writer data) is stored at the 13062306a36Sopenharmony_ci * beginning of the byte array. The referencing blk_lpos will point to the 13162306a36Sopenharmony_ci * ID before the wrap and the next data block will be at the logical 13262306a36Sopenharmony_ci * position adjacent the full data block after the wrap. 13362306a36Sopenharmony_ci * 13462306a36Sopenharmony_ci * Data rings have a @tail_lpos that points to the beginning of the oldest 13562306a36Sopenharmony_ci * data block and a @head_lpos that points to the logical position of the 13662306a36Sopenharmony_ci * next (not yet existing) data block. 13762306a36Sopenharmony_ci * 13862306a36Sopenharmony_ci * When a new data block should be created (and the ring is full), tail data 13962306a36Sopenharmony_ci * blocks will first be invalidated by putting their associated descriptors 14062306a36Sopenharmony_ci * into the reusable state and then pushing the @tail_lpos forward beyond 14162306a36Sopenharmony_ci * them. Then the @head_lpos is pushed forward and is associated with a new 14262306a36Sopenharmony_ci * descriptor. If a data block is not valid, the @tail_lpos cannot be 14362306a36Sopenharmony_ci * advanced beyond it. 14462306a36Sopenharmony_ci * 14562306a36Sopenharmony_ci * Info Array 14662306a36Sopenharmony_ci * ~~~~~~~~~~ 14762306a36Sopenharmony_ci * The general meta data of printk records are stored in printk_info structs, 14862306a36Sopenharmony_ci * stored in an array with the same number of elements as the descriptor ring. 14962306a36Sopenharmony_ci * Each info corresponds to the descriptor of the same index in the 15062306a36Sopenharmony_ci * descriptor ring. Info validity is confirmed by evaluating the corresponding 15162306a36Sopenharmony_ci * descriptor before and after loading the info. 15262306a36Sopenharmony_ci * 15362306a36Sopenharmony_ci * Usage 15462306a36Sopenharmony_ci * ----- 15562306a36Sopenharmony_ci * Here are some simple examples demonstrating writers and readers. For the 15662306a36Sopenharmony_ci * examples a global ringbuffer (test_rb) is available (which is not the 15762306a36Sopenharmony_ci * actual ringbuffer used by printk):: 15862306a36Sopenharmony_ci * 15962306a36Sopenharmony_ci * DEFINE_PRINTKRB(test_rb, 15, 5); 16062306a36Sopenharmony_ci * 16162306a36Sopenharmony_ci * This ringbuffer allows up to 32768 records (2 ^ 15) and has a size of 16262306a36Sopenharmony_ci * 1 MiB (2 ^ (15 + 5)) for text data. 16362306a36Sopenharmony_ci * 16462306a36Sopenharmony_ci * Sample writer code:: 16562306a36Sopenharmony_ci * 16662306a36Sopenharmony_ci * const char *textstr = "message text"; 16762306a36Sopenharmony_ci * struct prb_reserved_entry e; 16862306a36Sopenharmony_ci * struct printk_record r; 16962306a36Sopenharmony_ci * 17062306a36Sopenharmony_ci * // specify how much to allocate 17162306a36Sopenharmony_ci * prb_rec_init_wr(&r, strlen(textstr) + 1); 17262306a36Sopenharmony_ci * 17362306a36Sopenharmony_ci * if (prb_reserve(&e, &test_rb, &r)) { 17462306a36Sopenharmony_ci * snprintf(r.text_buf, r.text_buf_size, "%s", textstr); 17562306a36Sopenharmony_ci * 17662306a36Sopenharmony_ci * r.info->text_len = strlen(textstr); 17762306a36Sopenharmony_ci * r.info->ts_nsec = local_clock(); 17862306a36Sopenharmony_ci * r.info->caller_id = printk_caller_id(); 17962306a36Sopenharmony_ci * 18062306a36Sopenharmony_ci * // commit and finalize the record 18162306a36Sopenharmony_ci * prb_final_commit(&e); 18262306a36Sopenharmony_ci * } 18362306a36Sopenharmony_ci * 18462306a36Sopenharmony_ci * Note that additional writer functions are available to extend a record 18562306a36Sopenharmony_ci * after it has been committed but not yet finalized. This can be done as 18662306a36Sopenharmony_ci * long as no new records have been reserved and the caller is the same. 18762306a36Sopenharmony_ci * 18862306a36Sopenharmony_ci * Sample writer code (record extending):: 18962306a36Sopenharmony_ci * 19062306a36Sopenharmony_ci * // alternate rest of previous example 19162306a36Sopenharmony_ci * 19262306a36Sopenharmony_ci * r.info->text_len = strlen(textstr); 19362306a36Sopenharmony_ci * r.info->ts_nsec = local_clock(); 19462306a36Sopenharmony_ci * r.info->caller_id = printk_caller_id(); 19562306a36Sopenharmony_ci * 19662306a36Sopenharmony_ci * // commit the record (but do not finalize yet) 19762306a36Sopenharmony_ci * prb_commit(&e); 19862306a36Sopenharmony_ci * } 19962306a36Sopenharmony_ci * 20062306a36Sopenharmony_ci * ... 20162306a36Sopenharmony_ci * 20262306a36Sopenharmony_ci * // specify additional 5 bytes text space to extend 20362306a36Sopenharmony_ci * prb_rec_init_wr(&r, 5); 20462306a36Sopenharmony_ci * 20562306a36Sopenharmony_ci * // try to extend, but only if it does not exceed 32 bytes 20662306a36Sopenharmony_ci * if (prb_reserve_in_last(&e, &test_rb, &r, printk_caller_id(), 32)) { 20762306a36Sopenharmony_ci * snprintf(&r.text_buf[r.info->text_len], 20862306a36Sopenharmony_ci * r.text_buf_size - r.info->text_len, "hello"); 20962306a36Sopenharmony_ci * 21062306a36Sopenharmony_ci * r.info->text_len += 5; 21162306a36Sopenharmony_ci * 21262306a36Sopenharmony_ci * // commit and finalize the record 21362306a36Sopenharmony_ci * prb_final_commit(&e); 21462306a36Sopenharmony_ci * } 21562306a36Sopenharmony_ci * 21662306a36Sopenharmony_ci * Sample reader code:: 21762306a36Sopenharmony_ci * 21862306a36Sopenharmony_ci * struct printk_info info; 21962306a36Sopenharmony_ci * struct printk_record r; 22062306a36Sopenharmony_ci * char text_buf[32]; 22162306a36Sopenharmony_ci * u64 seq; 22262306a36Sopenharmony_ci * 22362306a36Sopenharmony_ci * prb_rec_init_rd(&r, &info, &text_buf[0], sizeof(text_buf)); 22462306a36Sopenharmony_ci * 22562306a36Sopenharmony_ci * prb_for_each_record(0, &test_rb, &seq, &r) { 22662306a36Sopenharmony_ci * if (info.seq != seq) 22762306a36Sopenharmony_ci * pr_warn("lost %llu records\n", info.seq - seq); 22862306a36Sopenharmony_ci * 22962306a36Sopenharmony_ci * if (info.text_len > r.text_buf_size) { 23062306a36Sopenharmony_ci * pr_warn("record %llu text truncated\n", info.seq); 23162306a36Sopenharmony_ci * text_buf[r.text_buf_size - 1] = 0; 23262306a36Sopenharmony_ci * } 23362306a36Sopenharmony_ci * 23462306a36Sopenharmony_ci * pr_info("%llu: %llu: %s\n", info.seq, info.ts_nsec, 23562306a36Sopenharmony_ci * &text_buf[0]); 23662306a36Sopenharmony_ci * } 23762306a36Sopenharmony_ci * 23862306a36Sopenharmony_ci * Note that additional less convenient reader functions are available to 23962306a36Sopenharmony_ci * allow complex record access. 24062306a36Sopenharmony_ci * 24162306a36Sopenharmony_ci * ABA Issues 24262306a36Sopenharmony_ci * ~~~~~~~~~~ 24362306a36Sopenharmony_ci * To help avoid ABA issues, descriptors are referenced by IDs (array index 24462306a36Sopenharmony_ci * values combined with tagged bits counting array wraps) and data blocks are 24562306a36Sopenharmony_ci * referenced by logical positions (array index values combined with tagged 24662306a36Sopenharmony_ci * bits counting array wraps). However, on 32-bit systems the number of 24762306a36Sopenharmony_ci * tagged bits is relatively small such that an ABA incident is (at least 24862306a36Sopenharmony_ci * theoretically) possible. For example, if 4 million maximally sized (1KiB) 24962306a36Sopenharmony_ci * printk messages were to occur in NMI context on a 32-bit system, the 25062306a36Sopenharmony_ci * interrupted context would not be able to recognize that the 32-bit integer 25162306a36Sopenharmony_ci * completely wrapped and thus represents a different data block than the one 25262306a36Sopenharmony_ci * the interrupted context expects. 25362306a36Sopenharmony_ci * 25462306a36Sopenharmony_ci * To help combat this possibility, additional state checking is performed 25562306a36Sopenharmony_ci * (such as using cmpxchg() even though set() would suffice). These extra 25662306a36Sopenharmony_ci * checks are commented as such and will hopefully catch any ABA issue that 25762306a36Sopenharmony_ci * a 32-bit system might experience. 25862306a36Sopenharmony_ci * 25962306a36Sopenharmony_ci * Memory Barriers 26062306a36Sopenharmony_ci * ~~~~~~~~~~~~~~~ 26162306a36Sopenharmony_ci * Multiple memory barriers are used. To simplify proving correctness and 26262306a36Sopenharmony_ci * generating litmus tests, lines of code related to memory barriers 26362306a36Sopenharmony_ci * (loads, stores, and the associated memory barriers) are labeled:: 26462306a36Sopenharmony_ci * 26562306a36Sopenharmony_ci * LMM(function:letter) 26662306a36Sopenharmony_ci * 26762306a36Sopenharmony_ci * Comments reference the labels using only the "function:letter" part. 26862306a36Sopenharmony_ci * 26962306a36Sopenharmony_ci * The memory barrier pairs and their ordering are: 27062306a36Sopenharmony_ci * 27162306a36Sopenharmony_ci * desc_reserve:D / desc_reserve:B 27262306a36Sopenharmony_ci * push descriptor tail (id), then push descriptor head (id) 27362306a36Sopenharmony_ci * 27462306a36Sopenharmony_ci * desc_reserve:D / data_push_tail:B 27562306a36Sopenharmony_ci * push data tail (lpos), then set new descriptor reserved (state) 27662306a36Sopenharmony_ci * 27762306a36Sopenharmony_ci * desc_reserve:D / desc_push_tail:C 27862306a36Sopenharmony_ci * push descriptor tail (id), then set new descriptor reserved (state) 27962306a36Sopenharmony_ci * 28062306a36Sopenharmony_ci * desc_reserve:D / prb_first_seq:C 28162306a36Sopenharmony_ci * push descriptor tail (id), then set new descriptor reserved (state) 28262306a36Sopenharmony_ci * 28362306a36Sopenharmony_ci * desc_reserve:F / desc_read:D 28462306a36Sopenharmony_ci * set new descriptor id and reserved (state), then allow writer changes 28562306a36Sopenharmony_ci * 28662306a36Sopenharmony_ci * data_alloc:A (or data_realloc:A) / desc_read:D 28762306a36Sopenharmony_ci * set old descriptor reusable (state), then modify new data block area 28862306a36Sopenharmony_ci * 28962306a36Sopenharmony_ci * data_alloc:A (or data_realloc:A) / data_push_tail:B 29062306a36Sopenharmony_ci * push data tail (lpos), then modify new data block area 29162306a36Sopenharmony_ci * 29262306a36Sopenharmony_ci * _prb_commit:B / desc_read:B 29362306a36Sopenharmony_ci * store writer changes, then set new descriptor committed (state) 29462306a36Sopenharmony_ci * 29562306a36Sopenharmony_ci * desc_reopen_last:A / _prb_commit:B 29662306a36Sopenharmony_ci * set descriptor reserved (state), then read descriptor data 29762306a36Sopenharmony_ci * 29862306a36Sopenharmony_ci * _prb_commit:B / desc_reserve:D 29962306a36Sopenharmony_ci * set new descriptor committed (state), then check descriptor head (id) 30062306a36Sopenharmony_ci * 30162306a36Sopenharmony_ci * data_push_tail:D / data_push_tail:A 30262306a36Sopenharmony_ci * set descriptor reusable (state), then push data tail (lpos) 30362306a36Sopenharmony_ci * 30462306a36Sopenharmony_ci * desc_push_tail:B / desc_reserve:D 30562306a36Sopenharmony_ci * set descriptor reusable (state), then push descriptor tail (id) 30662306a36Sopenharmony_ci */ 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci#define DATA_SIZE(data_ring) _DATA_SIZE((data_ring)->size_bits) 30962306a36Sopenharmony_ci#define DATA_SIZE_MASK(data_ring) (DATA_SIZE(data_ring) - 1) 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci#define DESCS_COUNT(desc_ring) _DESCS_COUNT((desc_ring)->count_bits) 31262306a36Sopenharmony_ci#define DESCS_COUNT_MASK(desc_ring) (DESCS_COUNT(desc_ring) - 1) 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci/* Determine the data array index from a logical position. */ 31562306a36Sopenharmony_ci#define DATA_INDEX(data_ring, lpos) ((lpos) & DATA_SIZE_MASK(data_ring)) 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci/* Determine the desc array index from an ID or sequence number. */ 31862306a36Sopenharmony_ci#define DESC_INDEX(desc_ring, n) ((n) & DESCS_COUNT_MASK(desc_ring)) 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci/* Determine how many times the data array has wrapped. */ 32162306a36Sopenharmony_ci#define DATA_WRAPS(data_ring, lpos) ((lpos) >> (data_ring)->size_bits) 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci/* Determine if a logical position refers to a data-less block. */ 32462306a36Sopenharmony_ci#define LPOS_DATALESS(lpos) ((lpos) & 1UL) 32562306a36Sopenharmony_ci#define BLK_DATALESS(blk) (LPOS_DATALESS((blk)->begin) && \ 32662306a36Sopenharmony_ci LPOS_DATALESS((blk)->next)) 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci/* Get the logical position at index 0 of the current wrap. */ 32962306a36Sopenharmony_ci#define DATA_THIS_WRAP_START_LPOS(data_ring, lpos) \ 33062306a36Sopenharmony_ci((lpos) & ~DATA_SIZE_MASK(data_ring)) 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci/* Get the ID for the same index of the previous wrap as the given ID. */ 33362306a36Sopenharmony_ci#define DESC_ID_PREV_WRAP(desc_ring, id) \ 33462306a36Sopenharmony_ciDESC_ID((id) - DESCS_COUNT(desc_ring)) 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci/* 33762306a36Sopenharmony_ci * A data block: mapped directly to the beginning of the data block area 33862306a36Sopenharmony_ci * specified as a logical position within the data ring. 33962306a36Sopenharmony_ci * 34062306a36Sopenharmony_ci * @id: the ID of the associated descriptor 34162306a36Sopenharmony_ci * @data: the writer data 34262306a36Sopenharmony_ci * 34362306a36Sopenharmony_ci * Note that the size of a data block is only known by its associated 34462306a36Sopenharmony_ci * descriptor. 34562306a36Sopenharmony_ci */ 34662306a36Sopenharmony_cistruct prb_data_block { 34762306a36Sopenharmony_ci unsigned long id; 34862306a36Sopenharmony_ci char data[]; 34962306a36Sopenharmony_ci}; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci/* 35262306a36Sopenharmony_ci * Return the descriptor associated with @n. @n can be either a 35362306a36Sopenharmony_ci * descriptor ID or a sequence number. 35462306a36Sopenharmony_ci */ 35562306a36Sopenharmony_cistatic struct prb_desc *to_desc(struct prb_desc_ring *desc_ring, u64 n) 35662306a36Sopenharmony_ci{ 35762306a36Sopenharmony_ci return &desc_ring->descs[DESC_INDEX(desc_ring, n)]; 35862306a36Sopenharmony_ci} 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci/* 36162306a36Sopenharmony_ci * Return the printk_info associated with @n. @n can be either a 36262306a36Sopenharmony_ci * descriptor ID or a sequence number. 36362306a36Sopenharmony_ci */ 36462306a36Sopenharmony_cistatic struct printk_info *to_info(struct prb_desc_ring *desc_ring, u64 n) 36562306a36Sopenharmony_ci{ 36662306a36Sopenharmony_ci return &desc_ring->infos[DESC_INDEX(desc_ring, n)]; 36762306a36Sopenharmony_ci} 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_cistatic struct prb_data_block *to_block(struct prb_data_ring *data_ring, 37062306a36Sopenharmony_ci unsigned long begin_lpos) 37162306a36Sopenharmony_ci{ 37262306a36Sopenharmony_ci return (void *)&data_ring->data[DATA_INDEX(data_ring, begin_lpos)]; 37362306a36Sopenharmony_ci} 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci/* 37662306a36Sopenharmony_ci * Increase the data size to account for data block meta data plus any 37762306a36Sopenharmony_ci * padding so that the adjacent data block is aligned on the ID size. 37862306a36Sopenharmony_ci */ 37962306a36Sopenharmony_cistatic unsigned int to_blk_size(unsigned int size) 38062306a36Sopenharmony_ci{ 38162306a36Sopenharmony_ci struct prb_data_block *db = NULL; 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci size += sizeof(*db); 38462306a36Sopenharmony_ci size = ALIGN(size, sizeof(db->id)); 38562306a36Sopenharmony_ci return size; 38662306a36Sopenharmony_ci} 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci/* 38962306a36Sopenharmony_ci * Sanity checker for reserve size. The ringbuffer code assumes that a data 39062306a36Sopenharmony_ci * block does not exceed the maximum possible size that could fit within the 39162306a36Sopenharmony_ci * ringbuffer. This function provides that basic size check so that the 39262306a36Sopenharmony_ci * assumption is safe. 39362306a36Sopenharmony_ci */ 39462306a36Sopenharmony_cistatic bool data_check_size(struct prb_data_ring *data_ring, unsigned int size) 39562306a36Sopenharmony_ci{ 39662306a36Sopenharmony_ci struct prb_data_block *db = NULL; 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci if (size == 0) 39962306a36Sopenharmony_ci return true; 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci /* 40262306a36Sopenharmony_ci * Ensure the alignment padded size could possibly fit in the data 40362306a36Sopenharmony_ci * array. The largest possible data block must still leave room for 40462306a36Sopenharmony_ci * at least the ID of the next block. 40562306a36Sopenharmony_ci */ 40662306a36Sopenharmony_ci size = to_blk_size(size); 40762306a36Sopenharmony_ci if (size > DATA_SIZE(data_ring) - sizeof(db->id)) 40862306a36Sopenharmony_ci return false; 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci return true; 41162306a36Sopenharmony_ci} 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci/* Query the state of a descriptor. */ 41462306a36Sopenharmony_cistatic enum desc_state get_desc_state(unsigned long id, 41562306a36Sopenharmony_ci unsigned long state_val) 41662306a36Sopenharmony_ci{ 41762306a36Sopenharmony_ci if (id != DESC_ID(state_val)) 41862306a36Sopenharmony_ci return desc_miss; 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci return DESC_STATE(state_val); 42162306a36Sopenharmony_ci} 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci/* 42462306a36Sopenharmony_ci * Get a copy of a specified descriptor and return its queried state. If the 42562306a36Sopenharmony_ci * descriptor is in an inconsistent state (miss or reserved), the caller can 42662306a36Sopenharmony_ci * only expect the descriptor's @state_var field to be valid. 42762306a36Sopenharmony_ci * 42862306a36Sopenharmony_ci * The sequence number and caller_id can be optionally retrieved. Like all 42962306a36Sopenharmony_ci * non-state_var data, they are only valid if the descriptor is in a 43062306a36Sopenharmony_ci * consistent state. 43162306a36Sopenharmony_ci */ 43262306a36Sopenharmony_cistatic enum desc_state desc_read(struct prb_desc_ring *desc_ring, 43362306a36Sopenharmony_ci unsigned long id, struct prb_desc *desc_out, 43462306a36Sopenharmony_ci u64 *seq_out, u32 *caller_id_out) 43562306a36Sopenharmony_ci{ 43662306a36Sopenharmony_ci struct printk_info *info = to_info(desc_ring, id); 43762306a36Sopenharmony_ci struct prb_desc *desc = to_desc(desc_ring, id); 43862306a36Sopenharmony_ci atomic_long_t *state_var = &desc->state_var; 43962306a36Sopenharmony_ci enum desc_state d_state; 44062306a36Sopenharmony_ci unsigned long state_val; 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci /* Check the descriptor state. */ 44362306a36Sopenharmony_ci state_val = atomic_long_read(state_var); /* LMM(desc_read:A) */ 44462306a36Sopenharmony_ci d_state = get_desc_state(id, state_val); 44562306a36Sopenharmony_ci if (d_state == desc_miss || d_state == desc_reserved) { 44662306a36Sopenharmony_ci /* 44762306a36Sopenharmony_ci * The descriptor is in an inconsistent state. Set at least 44862306a36Sopenharmony_ci * @state_var so that the caller can see the details of 44962306a36Sopenharmony_ci * the inconsistent state. 45062306a36Sopenharmony_ci */ 45162306a36Sopenharmony_ci goto out; 45262306a36Sopenharmony_ci } 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci /* 45562306a36Sopenharmony_ci * Guarantee the state is loaded before copying the descriptor 45662306a36Sopenharmony_ci * content. This avoids copying obsolete descriptor content that might 45762306a36Sopenharmony_ci * not apply to the descriptor state. This pairs with _prb_commit:B. 45862306a36Sopenharmony_ci * 45962306a36Sopenharmony_ci * Memory barrier involvement: 46062306a36Sopenharmony_ci * 46162306a36Sopenharmony_ci * If desc_read:A reads from _prb_commit:B, then desc_read:C reads 46262306a36Sopenharmony_ci * from _prb_commit:A. 46362306a36Sopenharmony_ci * 46462306a36Sopenharmony_ci * Relies on: 46562306a36Sopenharmony_ci * 46662306a36Sopenharmony_ci * WMB from _prb_commit:A to _prb_commit:B 46762306a36Sopenharmony_ci * matching 46862306a36Sopenharmony_ci * RMB from desc_read:A to desc_read:C 46962306a36Sopenharmony_ci */ 47062306a36Sopenharmony_ci smp_rmb(); /* LMM(desc_read:B) */ 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci /* 47362306a36Sopenharmony_ci * Copy the descriptor data. The data is not valid until the 47462306a36Sopenharmony_ci * state has been re-checked. A memcpy() for all of @desc 47562306a36Sopenharmony_ci * cannot be used because of the atomic_t @state_var field. 47662306a36Sopenharmony_ci */ 47762306a36Sopenharmony_ci if (desc_out) { 47862306a36Sopenharmony_ci memcpy(&desc_out->text_blk_lpos, &desc->text_blk_lpos, 47962306a36Sopenharmony_ci sizeof(desc_out->text_blk_lpos)); /* LMM(desc_read:C) */ 48062306a36Sopenharmony_ci } 48162306a36Sopenharmony_ci if (seq_out) 48262306a36Sopenharmony_ci *seq_out = info->seq; /* also part of desc_read:C */ 48362306a36Sopenharmony_ci if (caller_id_out) 48462306a36Sopenharmony_ci *caller_id_out = info->caller_id; /* also part of desc_read:C */ 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci /* 48762306a36Sopenharmony_ci * 1. Guarantee the descriptor content is loaded before re-checking 48862306a36Sopenharmony_ci * the state. This avoids reading an obsolete descriptor state 48962306a36Sopenharmony_ci * that may not apply to the copied content. This pairs with 49062306a36Sopenharmony_ci * desc_reserve:F. 49162306a36Sopenharmony_ci * 49262306a36Sopenharmony_ci * Memory barrier involvement: 49362306a36Sopenharmony_ci * 49462306a36Sopenharmony_ci * If desc_read:C reads from desc_reserve:G, then desc_read:E 49562306a36Sopenharmony_ci * reads from desc_reserve:F. 49662306a36Sopenharmony_ci * 49762306a36Sopenharmony_ci * Relies on: 49862306a36Sopenharmony_ci * 49962306a36Sopenharmony_ci * WMB from desc_reserve:F to desc_reserve:G 50062306a36Sopenharmony_ci * matching 50162306a36Sopenharmony_ci * RMB from desc_read:C to desc_read:E 50262306a36Sopenharmony_ci * 50362306a36Sopenharmony_ci * 2. Guarantee the record data is loaded before re-checking the 50462306a36Sopenharmony_ci * state. This avoids reading an obsolete descriptor state that may 50562306a36Sopenharmony_ci * not apply to the copied data. This pairs with data_alloc:A and 50662306a36Sopenharmony_ci * data_realloc:A. 50762306a36Sopenharmony_ci * 50862306a36Sopenharmony_ci * Memory barrier involvement: 50962306a36Sopenharmony_ci * 51062306a36Sopenharmony_ci * If copy_data:A reads from data_alloc:B, then desc_read:E 51162306a36Sopenharmony_ci * reads from desc_make_reusable:A. 51262306a36Sopenharmony_ci * 51362306a36Sopenharmony_ci * Relies on: 51462306a36Sopenharmony_ci * 51562306a36Sopenharmony_ci * MB from desc_make_reusable:A to data_alloc:B 51662306a36Sopenharmony_ci * matching 51762306a36Sopenharmony_ci * RMB from desc_read:C to desc_read:E 51862306a36Sopenharmony_ci * 51962306a36Sopenharmony_ci * Note: desc_make_reusable:A and data_alloc:B can be different 52062306a36Sopenharmony_ci * CPUs. However, the data_alloc:B CPU (which performs the 52162306a36Sopenharmony_ci * full memory barrier) must have previously seen 52262306a36Sopenharmony_ci * desc_make_reusable:A. 52362306a36Sopenharmony_ci */ 52462306a36Sopenharmony_ci smp_rmb(); /* LMM(desc_read:D) */ 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci /* 52762306a36Sopenharmony_ci * The data has been copied. Return the current descriptor state, 52862306a36Sopenharmony_ci * which may have changed since the load above. 52962306a36Sopenharmony_ci */ 53062306a36Sopenharmony_ci state_val = atomic_long_read(state_var); /* LMM(desc_read:E) */ 53162306a36Sopenharmony_ci d_state = get_desc_state(id, state_val); 53262306a36Sopenharmony_ciout: 53362306a36Sopenharmony_ci if (desc_out) 53462306a36Sopenharmony_ci atomic_long_set(&desc_out->state_var, state_val); 53562306a36Sopenharmony_ci return d_state; 53662306a36Sopenharmony_ci} 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci/* 53962306a36Sopenharmony_ci * Take a specified descriptor out of the finalized state by attempting 54062306a36Sopenharmony_ci * the transition from finalized to reusable. Either this context or some 54162306a36Sopenharmony_ci * other context will have been successful. 54262306a36Sopenharmony_ci */ 54362306a36Sopenharmony_cistatic void desc_make_reusable(struct prb_desc_ring *desc_ring, 54462306a36Sopenharmony_ci unsigned long id) 54562306a36Sopenharmony_ci{ 54662306a36Sopenharmony_ci unsigned long val_finalized = DESC_SV(id, desc_finalized); 54762306a36Sopenharmony_ci unsigned long val_reusable = DESC_SV(id, desc_reusable); 54862306a36Sopenharmony_ci struct prb_desc *desc = to_desc(desc_ring, id); 54962306a36Sopenharmony_ci atomic_long_t *state_var = &desc->state_var; 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci atomic_long_cmpxchg_relaxed(state_var, val_finalized, 55262306a36Sopenharmony_ci val_reusable); /* LMM(desc_make_reusable:A) */ 55362306a36Sopenharmony_ci} 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci/* 55662306a36Sopenharmony_ci * Given the text data ring, put the associated descriptor of each 55762306a36Sopenharmony_ci * data block from @lpos_begin until @lpos_end into the reusable state. 55862306a36Sopenharmony_ci * 55962306a36Sopenharmony_ci * If there is any problem making the associated descriptor reusable, either 56062306a36Sopenharmony_ci * the descriptor has not yet been finalized or another writer context has 56162306a36Sopenharmony_ci * already pushed the tail lpos past the problematic data block. Regardless, 56262306a36Sopenharmony_ci * on error the caller can re-load the tail lpos to determine the situation. 56362306a36Sopenharmony_ci */ 56462306a36Sopenharmony_cistatic bool data_make_reusable(struct printk_ringbuffer *rb, 56562306a36Sopenharmony_ci unsigned long lpos_begin, 56662306a36Sopenharmony_ci unsigned long lpos_end, 56762306a36Sopenharmony_ci unsigned long *lpos_out) 56862306a36Sopenharmony_ci{ 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci struct prb_data_ring *data_ring = &rb->text_data_ring; 57162306a36Sopenharmony_ci struct prb_desc_ring *desc_ring = &rb->desc_ring; 57262306a36Sopenharmony_ci struct prb_data_block *blk; 57362306a36Sopenharmony_ci enum desc_state d_state; 57462306a36Sopenharmony_ci struct prb_desc desc; 57562306a36Sopenharmony_ci struct prb_data_blk_lpos *blk_lpos = &desc.text_blk_lpos; 57662306a36Sopenharmony_ci unsigned long id; 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci /* Loop until @lpos_begin has advanced to or beyond @lpos_end. */ 57962306a36Sopenharmony_ci while ((lpos_end - lpos_begin) - 1 < DATA_SIZE(data_ring)) { 58062306a36Sopenharmony_ci blk = to_block(data_ring, lpos_begin); 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci /* 58362306a36Sopenharmony_ci * Load the block ID from the data block. This is a data race 58462306a36Sopenharmony_ci * against a writer that may have newly reserved this data 58562306a36Sopenharmony_ci * area. If the loaded value matches a valid descriptor ID, 58662306a36Sopenharmony_ci * the blk_lpos of that descriptor will be checked to make 58762306a36Sopenharmony_ci * sure it points back to this data block. If the check fails, 58862306a36Sopenharmony_ci * the data area has been recycled by another writer. 58962306a36Sopenharmony_ci */ 59062306a36Sopenharmony_ci id = blk->id; /* LMM(data_make_reusable:A) */ 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci d_state = desc_read(desc_ring, id, &desc, 59362306a36Sopenharmony_ci NULL, NULL); /* LMM(data_make_reusable:B) */ 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci switch (d_state) { 59662306a36Sopenharmony_ci case desc_miss: 59762306a36Sopenharmony_ci case desc_reserved: 59862306a36Sopenharmony_ci case desc_committed: 59962306a36Sopenharmony_ci return false; 60062306a36Sopenharmony_ci case desc_finalized: 60162306a36Sopenharmony_ci /* 60262306a36Sopenharmony_ci * This data block is invalid if the descriptor 60362306a36Sopenharmony_ci * does not point back to it. 60462306a36Sopenharmony_ci */ 60562306a36Sopenharmony_ci if (blk_lpos->begin != lpos_begin) 60662306a36Sopenharmony_ci return false; 60762306a36Sopenharmony_ci desc_make_reusable(desc_ring, id); 60862306a36Sopenharmony_ci break; 60962306a36Sopenharmony_ci case desc_reusable: 61062306a36Sopenharmony_ci /* 61162306a36Sopenharmony_ci * This data block is invalid if the descriptor 61262306a36Sopenharmony_ci * does not point back to it. 61362306a36Sopenharmony_ci */ 61462306a36Sopenharmony_ci if (blk_lpos->begin != lpos_begin) 61562306a36Sopenharmony_ci return false; 61662306a36Sopenharmony_ci break; 61762306a36Sopenharmony_ci } 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci /* Advance @lpos_begin to the next data block. */ 62062306a36Sopenharmony_ci lpos_begin = blk_lpos->next; 62162306a36Sopenharmony_ci } 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci *lpos_out = lpos_begin; 62462306a36Sopenharmony_ci return true; 62562306a36Sopenharmony_ci} 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci/* 62862306a36Sopenharmony_ci * Advance the data ring tail to at least @lpos. This function puts 62962306a36Sopenharmony_ci * descriptors into the reusable state if the tail is pushed beyond 63062306a36Sopenharmony_ci * their associated data block. 63162306a36Sopenharmony_ci */ 63262306a36Sopenharmony_cistatic bool data_push_tail(struct printk_ringbuffer *rb, unsigned long lpos) 63362306a36Sopenharmony_ci{ 63462306a36Sopenharmony_ci struct prb_data_ring *data_ring = &rb->text_data_ring; 63562306a36Sopenharmony_ci unsigned long tail_lpos_new; 63662306a36Sopenharmony_ci unsigned long tail_lpos; 63762306a36Sopenharmony_ci unsigned long next_lpos; 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_ci /* If @lpos is from a data-less block, there is nothing to do. */ 64062306a36Sopenharmony_ci if (LPOS_DATALESS(lpos)) 64162306a36Sopenharmony_ci return true; 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci /* 64462306a36Sopenharmony_ci * Any descriptor states that have transitioned to reusable due to the 64562306a36Sopenharmony_ci * data tail being pushed to this loaded value will be visible to this 64662306a36Sopenharmony_ci * CPU. This pairs with data_push_tail:D. 64762306a36Sopenharmony_ci * 64862306a36Sopenharmony_ci * Memory barrier involvement: 64962306a36Sopenharmony_ci * 65062306a36Sopenharmony_ci * If data_push_tail:A reads from data_push_tail:D, then this CPU can 65162306a36Sopenharmony_ci * see desc_make_reusable:A. 65262306a36Sopenharmony_ci * 65362306a36Sopenharmony_ci * Relies on: 65462306a36Sopenharmony_ci * 65562306a36Sopenharmony_ci * MB from desc_make_reusable:A to data_push_tail:D 65662306a36Sopenharmony_ci * matches 65762306a36Sopenharmony_ci * READFROM from data_push_tail:D to data_push_tail:A 65862306a36Sopenharmony_ci * thus 65962306a36Sopenharmony_ci * READFROM from desc_make_reusable:A to this CPU 66062306a36Sopenharmony_ci */ 66162306a36Sopenharmony_ci tail_lpos = atomic_long_read(&data_ring->tail_lpos); /* LMM(data_push_tail:A) */ 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci /* 66462306a36Sopenharmony_ci * Loop until the tail lpos is at or beyond @lpos. This condition 66562306a36Sopenharmony_ci * may already be satisfied, resulting in no full memory barrier 66662306a36Sopenharmony_ci * from data_push_tail:D being performed. However, since this CPU 66762306a36Sopenharmony_ci * sees the new tail lpos, any descriptor states that transitioned to 66862306a36Sopenharmony_ci * the reusable state must already be visible. 66962306a36Sopenharmony_ci */ 67062306a36Sopenharmony_ci while ((lpos - tail_lpos) - 1 < DATA_SIZE(data_ring)) { 67162306a36Sopenharmony_ci /* 67262306a36Sopenharmony_ci * Make all descriptors reusable that are associated with 67362306a36Sopenharmony_ci * data blocks before @lpos. 67462306a36Sopenharmony_ci */ 67562306a36Sopenharmony_ci if (!data_make_reusable(rb, tail_lpos, lpos, &next_lpos)) { 67662306a36Sopenharmony_ci /* 67762306a36Sopenharmony_ci * 1. Guarantee the block ID loaded in 67862306a36Sopenharmony_ci * data_make_reusable() is performed before 67962306a36Sopenharmony_ci * reloading the tail lpos. The failed 68062306a36Sopenharmony_ci * data_make_reusable() may be due to a newly 68162306a36Sopenharmony_ci * recycled data area causing the tail lpos to 68262306a36Sopenharmony_ci * have been previously pushed. This pairs with 68362306a36Sopenharmony_ci * data_alloc:A and data_realloc:A. 68462306a36Sopenharmony_ci * 68562306a36Sopenharmony_ci * Memory barrier involvement: 68662306a36Sopenharmony_ci * 68762306a36Sopenharmony_ci * If data_make_reusable:A reads from data_alloc:B, 68862306a36Sopenharmony_ci * then data_push_tail:C reads from 68962306a36Sopenharmony_ci * data_push_tail:D. 69062306a36Sopenharmony_ci * 69162306a36Sopenharmony_ci * Relies on: 69262306a36Sopenharmony_ci * 69362306a36Sopenharmony_ci * MB from data_push_tail:D to data_alloc:B 69462306a36Sopenharmony_ci * matching 69562306a36Sopenharmony_ci * RMB from data_make_reusable:A to 69662306a36Sopenharmony_ci * data_push_tail:C 69762306a36Sopenharmony_ci * 69862306a36Sopenharmony_ci * Note: data_push_tail:D and data_alloc:B can be 69962306a36Sopenharmony_ci * different CPUs. However, the data_alloc:B 70062306a36Sopenharmony_ci * CPU (which performs the full memory 70162306a36Sopenharmony_ci * barrier) must have previously seen 70262306a36Sopenharmony_ci * data_push_tail:D. 70362306a36Sopenharmony_ci * 70462306a36Sopenharmony_ci * 2. Guarantee the descriptor state loaded in 70562306a36Sopenharmony_ci * data_make_reusable() is performed before 70662306a36Sopenharmony_ci * reloading the tail lpos. The failed 70762306a36Sopenharmony_ci * data_make_reusable() may be due to a newly 70862306a36Sopenharmony_ci * recycled descriptor causing the tail lpos to 70962306a36Sopenharmony_ci * have been previously pushed. This pairs with 71062306a36Sopenharmony_ci * desc_reserve:D. 71162306a36Sopenharmony_ci * 71262306a36Sopenharmony_ci * Memory barrier involvement: 71362306a36Sopenharmony_ci * 71462306a36Sopenharmony_ci * If data_make_reusable:B reads from 71562306a36Sopenharmony_ci * desc_reserve:F, then data_push_tail:C reads 71662306a36Sopenharmony_ci * from data_push_tail:D. 71762306a36Sopenharmony_ci * 71862306a36Sopenharmony_ci * Relies on: 71962306a36Sopenharmony_ci * 72062306a36Sopenharmony_ci * MB from data_push_tail:D to desc_reserve:F 72162306a36Sopenharmony_ci * matching 72262306a36Sopenharmony_ci * RMB from data_make_reusable:B to 72362306a36Sopenharmony_ci * data_push_tail:C 72462306a36Sopenharmony_ci * 72562306a36Sopenharmony_ci * Note: data_push_tail:D and desc_reserve:F can 72662306a36Sopenharmony_ci * be different CPUs. However, the 72762306a36Sopenharmony_ci * desc_reserve:F CPU (which performs the 72862306a36Sopenharmony_ci * full memory barrier) must have previously 72962306a36Sopenharmony_ci * seen data_push_tail:D. 73062306a36Sopenharmony_ci */ 73162306a36Sopenharmony_ci smp_rmb(); /* LMM(data_push_tail:B) */ 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci tail_lpos_new = atomic_long_read(&data_ring->tail_lpos 73462306a36Sopenharmony_ci ); /* LMM(data_push_tail:C) */ 73562306a36Sopenharmony_ci if (tail_lpos_new == tail_lpos) 73662306a36Sopenharmony_ci return false; 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ci /* Another CPU pushed the tail. Try again. */ 73962306a36Sopenharmony_ci tail_lpos = tail_lpos_new; 74062306a36Sopenharmony_ci continue; 74162306a36Sopenharmony_ci } 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci /* 74462306a36Sopenharmony_ci * Guarantee any descriptor states that have transitioned to 74562306a36Sopenharmony_ci * reusable are stored before pushing the tail lpos. A full 74662306a36Sopenharmony_ci * memory barrier is needed since other CPUs may have made 74762306a36Sopenharmony_ci * the descriptor states reusable. This pairs with 74862306a36Sopenharmony_ci * data_push_tail:A. 74962306a36Sopenharmony_ci */ 75062306a36Sopenharmony_ci if (atomic_long_try_cmpxchg(&data_ring->tail_lpos, &tail_lpos, 75162306a36Sopenharmony_ci next_lpos)) { /* LMM(data_push_tail:D) */ 75262306a36Sopenharmony_ci break; 75362306a36Sopenharmony_ci } 75462306a36Sopenharmony_ci } 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci return true; 75762306a36Sopenharmony_ci} 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci/* 76062306a36Sopenharmony_ci * Advance the desc ring tail. This function advances the tail by one 76162306a36Sopenharmony_ci * descriptor, thus invalidating the oldest descriptor. Before advancing 76262306a36Sopenharmony_ci * the tail, the tail descriptor is made reusable and all data blocks up to 76362306a36Sopenharmony_ci * and including the descriptor's data block are invalidated (i.e. the data 76462306a36Sopenharmony_ci * ring tail is pushed past the data block of the descriptor being made 76562306a36Sopenharmony_ci * reusable). 76662306a36Sopenharmony_ci */ 76762306a36Sopenharmony_cistatic bool desc_push_tail(struct printk_ringbuffer *rb, 76862306a36Sopenharmony_ci unsigned long tail_id) 76962306a36Sopenharmony_ci{ 77062306a36Sopenharmony_ci struct prb_desc_ring *desc_ring = &rb->desc_ring; 77162306a36Sopenharmony_ci enum desc_state d_state; 77262306a36Sopenharmony_ci struct prb_desc desc; 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ci d_state = desc_read(desc_ring, tail_id, &desc, NULL, NULL); 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci switch (d_state) { 77762306a36Sopenharmony_ci case desc_miss: 77862306a36Sopenharmony_ci /* 77962306a36Sopenharmony_ci * If the ID is exactly 1 wrap behind the expected, it is 78062306a36Sopenharmony_ci * in the process of being reserved by another writer and 78162306a36Sopenharmony_ci * must be considered reserved. 78262306a36Sopenharmony_ci */ 78362306a36Sopenharmony_ci if (DESC_ID(atomic_long_read(&desc.state_var)) == 78462306a36Sopenharmony_ci DESC_ID_PREV_WRAP(desc_ring, tail_id)) { 78562306a36Sopenharmony_ci return false; 78662306a36Sopenharmony_ci } 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci /* 78962306a36Sopenharmony_ci * The ID has changed. Another writer must have pushed the 79062306a36Sopenharmony_ci * tail and recycled the descriptor already. Success is 79162306a36Sopenharmony_ci * returned because the caller is only interested in the 79262306a36Sopenharmony_ci * specified tail being pushed, which it was. 79362306a36Sopenharmony_ci */ 79462306a36Sopenharmony_ci return true; 79562306a36Sopenharmony_ci case desc_reserved: 79662306a36Sopenharmony_ci case desc_committed: 79762306a36Sopenharmony_ci return false; 79862306a36Sopenharmony_ci case desc_finalized: 79962306a36Sopenharmony_ci desc_make_reusable(desc_ring, tail_id); 80062306a36Sopenharmony_ci break; 80162306a36Sopenharmony_ci case desc_reusable: 80262306a36Sopenharmony_ci break; 80362306a36Sopenharmony_ci } 80462306a36Sopenharmony_ci 80562306a36Sopenharmony_ci /* 80662306a36Sopenharmony_ci * Data blocks must be invalidated before their associated 80762306a36Sopenharmony_ci * descriptor can be made available for recycling. Invalidating 80862306a36Sopenharmony_ci * them later is not possible because there is no way to trust 80962306a36Sopenharmony_ci * data blocks once their associated descriptor is gone. 81062306a36Sopenharmony_ci */ 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci if (!data_push_tail(rb, desc.text_blk_lpos.next)) 81362306a36Sopenharmony_ci return false; 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_ci /* 81662306a36Sopenharmony_ci * Check the next descriptor after @tail_id before pushing the tail 81762306a36Sopenharmony_ci * to it because the tail must always be in a finalized or reusable 81862306a36Sopenharmony_ci * state. The implementation of prb_first_seq() relies on this. 81962306a36Sopenharmony_ci * 82062306a36Sopenharmony_ci * A successful read implies that the next descriptor is less than or 82162306a36Sopenharmony_ci * equal to @head_id so there is no risk of pushing the tail past the 82262306a36Sopenharmony_ci * head. 82362306a36Sopenharmony_ci */ 82462306a36Sopenharmony_ci d_state = desc_read(desc_ring, DESC_ID(tail_id + 1), &desc, 82562306a36Sopenharmony_ci NULL, NULL); /* LMM(desc_push_tail:A) */ 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci if (d_state == desc_finalized || d_state == desc_reusable) { 82862306a36Sopenharmony_ci /* 82962306a36Sopenharmony_ci * Guarantee any descriptor states that have transitioned to 83062306a36Sopenharmony_ci * reusable are stored before pushing the tail ID. This allows 83162306a36Sopenharmony_ci * verifying the recycled descriptor state. A full memory 83262306a36Sopenharmony_ci * barrier is needed since other CPUs may have made the 83362306a36Sopenharmony_ci * descriptor states reusable. This pairs with desc_reserve:D. 83462306a36Sopenharmony_ci */ 83562306a36Sopenharmony_ci atomic_long_cmpxchg(&desc_ring->tail_id, tail_id, 83662306a36Sopenharmony_ci DESC_ID(tail_id + 1)); /* LMM(desc_push_tail:B) */ 83762306a36Sopenharmony_ci } else { 83862306a36Sopenharmony_ci /* 83962306a36Sopenharmony_ci * Guarantee the last state load from desc_read() is before 84062306a36Sopenharmony_ci * reloading @tail_id in order to see a new tail ID in the 84162306a36Sopenharmony_ci * case that the descriptor has been recycled. This pairs 84262306a36Sopenharmony_ci * with desc_reserve:D. 84362306a36Sopenharmony_ci * 84462306a36Sopenharmony_ci * Memory barrier involvement: 84562306a36Sopenharmony_ci * 84662306a36Sopenharmony_ci * If desc_push_tail:A reads from desc_reserve:F, then 84762306a36Sopenharmony_ci * desc_push_tail:D reads from desc_push_tail:B. 84862306a36Sopenharmony_ci * 84962306a36Sopenharmony_ci * Relies on: 85062306a36Sopenharmony_ci * 85162306a36Sopenharmony_ci * MB from desc_push_tail:B to desc_reserve:F 85262306a36Sopenharmony_ci * matching 85362306a36Sopenharmony_ci * RMB from desc_push_tail:A to desc_push_tail:D 85462306a36Sopenharmony_ci * 85562306a36Sopenharmony_ci * Note: desc_push_tail:B and desc_reserve:F can be different 85662306a36Sopenharmony_ci * CPUs. However, the desc_reserve:F CPU (which performs 85762306a36Sopenharmony_ci * the full memory barrier) must have previously seen 85862306a36Sopenharmony_ci * desc_push_tail:B. 85962306a36Sopenharmony_ci */ 86062306a36Sopenharmony_ci smp_rmb(); /* LMM(desc_push_tail:C) */ 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_ci /* 86362306a36Sopenharmony_ci * Re-check the tail ID. The descriptor following @tail_id is 86462306a36Sopenharmony_ci * not in an allowed tail state. But if the tail has since 86562306a36Sopenharmony_ci * been moved by another CPU, then it does not matter. 86662306a36Sopenharmony_ci */ 86762306a36Sopenharmony_ci if (atomic_long_read(&desc_ring->tail_id) == tail_id) /* LMM(desc_push_tail:D) */ 86862306a36Sopenharmony_ci return false; 86962306a36Sopenharmony_ci } 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_ci return true; 87262306a36Sopenharmony_ci} 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ci/* Reserve a new descriptor, invalidating the oldest if necessary. */ 87562306a36Sopenharmony_cistatic bool desc_reserve(struct printk_ringbuffer *rb, unsigned long *id_out) 87662306a36Sopenharmony_ci{ 87762306a36Sopenharmony_ci struct prb_desc_ring *desc_ring = &rb->desc_ring; 87862306a36Sopenharmony_ci unsigned long prev_state_val; 87962306a36Sopenharmony_ci unsigned long id_prev_wrap; 88062306a36Sopenharmony_ci struct prb_desc *desc; 88162306a36Sopenharmony_ci unsigned long head_id; 88262306a36Sopenharmony_ci unsigned long id; 88362306a36Sopenharmony_ci 88462306a36Sopenharmony_ci head_id = atomic_long_read(&desc_ring->head_id); /* LMM(desc_reserve:A) */ 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_ci do { 88762306a36Sopenharmony_ci id = DESC_ID(head_id + 1); 88862306a36Sopenharmony_ci id_prev_wrap = DESC_ID_PREV_WRAP(desc_ring, id); 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_ci /* 89162306a36Sopenharmony_ci * Guarantee the head ID is read before reading the tail ID. 89262306a36Sopenharmony_ci * Since the tail ID is updated before the head ID, this 89362306a36Sopenharmony_ci * guarantees that @id_prev_wrap is never ahead of the tail 89462306a36Sopenharmony_ci * ID. This pairs with desc_reserve:D. 89562306a36Sopenharmony_ci * 89662306a36Sopenharmony_ci * Memory barrier involvement: 89762306a36Sopenharmony_ci * 89862306a36Sopenharmony_ci * If desc_reserve:A reads from desc_reserve:D, then 89962306a36Sopenharmony_ci * desc_reserve:C reads from desc_push_tail:B. 90062306a36Sopenharmony_ci * 90162306a36Sopenharmony_ci * Relies on: 90262306a36Sopenharmony_ci * 90362306a36Sopenharmony_ci * MB from desc_push_tail:B to desc_reserve:D 90462306a36Sopenharmony_ci * matching 90562306a36Sopenharmony_ci * RMB from desc_reserve:A to desc_reserve:C 90662306a36Sopenharmony_ci * 90762306a36Sopenharmony_ci * Note: desc_push_tail:B and desc_reserve:D can be different 90862306a36Sopenharmony_ci * CPUs. However, the desc_reserve:D CPU (which performs 90962306a36Sopenharmony_ci * the full memory barrier) must have previously seen 91062306a36Sopenharmony_ci * desc_push_tail:B. 91162306a36Sopenharmony_ci */ 91262306a36Sopenharmony_ci smp_rmb(); /* LMM(desc_reserve:B) */ 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_ci if (id_prev_wrap == atomic_long_read(&desc_ring->tail_id 91562306a36Sopenharmony_ci )) { /* LMM(desc_reserve:C) */ 91662306a36Sopenharmony_ci /* 91762306a36Sopenharmony_ci * Make space for the new descriptor by 91862306a36Sopenharmony_ci * advancing the tail. 91962306a36Sopenharmony_ci */ 92062306a36Sopenharmony_ci if (!desc_push_tail(rb, id_prev_wrap)) 92162306a36Sopenharmony_ci return false; 92262306a36Sopenharmony_ci } 92362306a36Sopenharmony_ci 92462306a36Sopenharmony_ci /* 92562306a36Sopenharmony_ci * 1. Guarantee the tail ID is read before validating the 92662306a36Sopenharmony_ci * recycled descriptor state. A read memory barrier is 92762306a36Sopenharmony_ci * sufficient for this. This pairs with desc_push_tail:B. 92862306a36Sopenharmony_ci * 92962306a36Sopenharmony_ci * Memory barrier involvement: 93062306a36Sopenharmony_ci * 93162306a36Sopenharmony_ci * If desc_reserve:C reads from desc_push_tail:B, then 93262306a36Sopenharmony_ci * desc_reserve:E reads from desc_make_reusable:A. 93362306a36Sopenharmony_ci * 93462306a36Sopenharmony_ci * Relies on: 93562306a36Sopenharmony_ci * 93662306a36Sopenharmony_ci * MB from desc_make_reusable:A to desc_push_tail:B 93762306a36Sopenharmony_ci * matching 93862306a36Sopenharmony_ci * RMB from desc_reserve:C to desc_reserve:E 93962306a36Sopenharmony_ci * 94062306a36Sopenharmony_ci * Note: desc_make_reusable:A and desc_push_tail:B can be 94162306a36Sopenharmony_ci * different CPUs. However, the desc_push_tail:B CPU 94262306a36Sopenharmony_ci * (which performs the full memory barrier) must have 94362306a36Sopenharmony_ci * previously seen desc_make_reusable:A. 94462306a36Sopenharmony_ci * 94562306a36Sopenharmony_ci * 2. Guarantee the tail ID is stored before storing the head 94662306a36Sopenharmony_ci * ID. This pairs with desc_reserve:B. 94762306a36Sopenharmony_ci * 94862306a36Sopenharmony_ci * 3. Guarantee any data ring tail changes are stored before 94962306a36Sopenharmony_ci * recycling the descriptor. Data ring tail changes can 95062306a36Sopenharmony_ci * happen via desc_push_tail()->data_push_tail(). A full 95162306a36Sopenharmony_ci * memory barrier is needed since another CPU may have 95262306a36Sopenharmony_ci * pushed the data ring tails. This pairs with 95362306a36Sopenharmony_ci * data_push_tail:B. 95462306a36Sopenharmony_ci * 95562306a36Sopenharmony_ci * 4. Guarantee a new tail ID is stored before recycling the 95662306a36Sopenharmony_ci * descriptor. A full memory barrier is needed since 95762306a36Sopenharmony_ci * another CPU may have pushed the tail ID. This pairs 95862306a36Sopenharmony_ci * with desc_push_tail:C and this also pairs with 95962306a36Sopenharmony_ci * prb_first_seq:C. 96062306a36Sopenharmony_ci * 96162306a36Sopenharmony_ci * 5. Guarantee the head ID is stored before trying to 96262306a36Sopenharmony_ci * finalize the previous descriptor. This pairs with 96362306a36Sopenharmony_ci * _prb_commit:B. 96462306a36Sopenharmony_ci */ 96562306a36Sopenharmony_ci } while (!atomic_long_try_cmpxchg(&desc_ring->head_id, &head_id, 96662306a36Sopenharmony_ci id)); /* LMM(desc_reserve:D) */ 96762306a36Sopenharmony_ci 96862306a36Sopenharmony_ci desc = to_desc(desc_ring, id); 96962306a36Sopenharmony_ci 97062306a36Sopenharmony_ci /* 97162306a36Sopenharmony_ci * If the descriptor has been recycled, verify the old state val. 97262306a36Sopenharmony_ci * See "ABA Issues" about why this verification is performed. 97362306a36Sopenharmony_ci */ 97462306a36Sopenharmony_ci prev_state_val = atomic_long_read(&desc->state_var); /* LMM(desc_reserve:E) */ 97562306a36Sopenharmony_ci if (prev_state_val && 97662306a36Sopenharmony_ci get_desc_state(id_prev_wrap, prev_state_val) != desc_reusable) { 97762306a36Sopenharmony_ci WARN_ON_ONCE(1); 97862306a36Sopenharmony_ci return false; 97962306a36Sopenharmony_ci } 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_ci /* 98262306a36Sopenharmony_ci * Assign the descriptor a new ID and set its state to reserved. 98362306a36Sopenharmony_ci * See "ABA Issues" about why cmpxchg() instead of set() is used. 98462306a36Sopenharmony_ci * 98562306a36Sopenharmony_ci * Guarantee the new descriptor ID and state is stored before making 98662306a36Sopenharmony_ci * any other changes. A write memory barrier is sufficient for this. 98762306a36Sopenharmony_ci * This pairs with desc_read:D. 98862306a36Sopenharmony_ci */ 98962306a36Sopenharmony_ci if (!atomic_long_try_cmpxchg(&desc->state_var, &prev_state_val, 99062306a36Sopenharmony_ci DESC_SV(id, desc_reserved))) { /* LMM(desc_reserve:F) */ 99162306a36Sopenharmony_ci WARN_ON_ONCE(1); 99262306a36Sopenharmony_ci return false; 99362306a36Sopenharmony_ci } 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_ci /* Now data in @desc can be modified: LMM(desc_reserve:G) */ 99662306a36Sopenharmony_ci 99762306a36Sopenharmony_ci *id_out = id; 99862306a36Sopenharmony_ci return true; 99962306a36Sopenharmony_ci} 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_ci/* Determine the end of a data block. */ 100262306a36Sopenharmony_cistatic unsigned long get_next_lpos(struct prb_data_ring *data_ring, 100362306a36Sopenharmony_ci unsigned long lpos, unsigned int size) 100462306a36Sopenharmony_ci{ 100562306a36Sopenharmony_ci unsigned long begin_lpos; 100662306a36Sopenharmony_ci unsigned long next_lpos; 100762306a36Sopenharmony_ci 100862306a36Sopenharmony_ci begin_lpos = lpos; 100962306a36Sopenharmony_ci next_lpos = lpos + size; 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ci /* First check if the data block does not wrap. */ 101262306a36Sopenharmony_ci if (DATA_WRAPS(data_ring, begin_lpos) == DATA_WRAPS(data_ring, next_lpos)) 101362306a36Sopenharmony_ci return next_lpos; 101462306a36Sopenharmony_ci 101562306a36Sopenharmony_ci /* Wrapping data blocks store their data at the beginning. */ 101662306a36Sopenharmony_ci return (DATA_THIS_WRAP_START_LPOS(data_ring, next_lpos) + size); 101762306a36Sopenharmony_ci} 101862306a36Sopenharmony_ci 101962306a36Sopenharmony_ci/* 102062306a36Sopenharmony_ci * Allocate a new data block, invalidating the oldest data block(s) 102162306a36Sopenharmony_ci * if necessary. This function also associates the data block with 102262306a36Sopenharmony_ci * a specified descriptor. 102362306a36Sopenharmony_ci */ 102462306a36Sopenharmony_cistatic char *data_alloc(struct printk_ringbuffer *rb, unsigned int size, 102562306a36Sopenharmony_ci struct prb_data_blk_lpos *blk_lpos, unsigned long id) 102662306a36Sopenharmony_ci{ 102762306a36Sopenharmony_ci struct prb_data_ring *data_ring = &rb->text_data_ring; 102862306a36Sopenharmony_ci struct prb_data_block *blk; 102962306a36Sopenharmony_ci unsigned long begin_lpos; 103062306a36Sopenharmony_ci unsigned long next_lpos; 103162306a36Sopenharmony_ci 103262306a36Sopenharmony_ci if (size == 0) { 103362306a36Sopenharmony_ci /* Specify a data-less block. */ 103462306a36Sopenharmony_ci blk_lpos->begin = NO_LPOS; 103562306a36Sopenharmony_ci blk_lpos->next = NO_LPOS; 103662306a36Sopenharmony_ci return NULL; 103762306a36Sopenharmony_ci } 103862306a36Sopenharmony_ci 103962306a36Sopenharmony_ci size = to_blk_size(size); 104062306a36Sopenharmony_ci 104162306a36Sopenharmony_ci begin_lpos = atomic_long_read(&data_ring->head_lpos); 104262306a36Sopenharmony_ci 104362306a36Sopenharmony_ci do { 104462306a36Sopenharmony_ci next_lpos = get_next_lpos(data_ring, begin_lpos, size); 104562306a36Sopenharmony_ci 104662306a36Sopenharmony_ci if (!data_push_tail(rb, next_lpos - DATA_SIZE(data_ring))) { 104762306a36Sopenharmony_ci /* Failed to allocate, specify a data-less block. */ 104862306a36Sopenharmony_ci blk_lpos->begin = FAILED_LPOS; 104962306a36Sopenharmony_ci blk_lpos->next = FAILED_LPOS; 105062306a36Sopenharmony_ci return NULL; 105162306a36Sopenharmony_ci } 105262306a36Sopenharmony_ci 105362306a36Sopenharmony_ci /* 105462306a36Sopenharmony_ci * 1. Guarantee any descriptor states that have transitioned 105562306a36Sopenharmony_ci * to reusable are stored before modifying the newly 105662306a36Sopenharmony_ci * allocated data area. A full memory barrier is needed 105762306a36Sopenharmony_ci * since other CPUs may have made the descriptor states 105862306a36Sopenharmony_ci * reusable. See data_push_tail:A about why the reusable 105962306a36Sopenharmony_ci * states are visible. This pairs with desc_read:D. 106062306a36Sopenharmony_ci * 106162306a36Sopenharmony_ci * 2. Guarantee any updated tail lpos is stored before 106262306a36Sopenharmony_ci * modifying the newly allocated data area. Another CPU may 106362306a36Sopenharmony_ci * be in data_make_reusable() and is reading a block ID 106462306a36Sopenharmony_ci * from this area. data_make_reusable() can handle reading 106562306a36Sopenharmony_ci * a garbage block ID value, but then it must be able to 106662306a36Sopenharmony_ci * load a new tail lpos. A full memory barrier is needed 106762306a36Sopenharmony_ci * since other CPUs may have updated the tail lpos. This 106862306a36Sopenharmony_ci * pairs with data_push_tail:B. 106962306a36Sopenharmony_ci */ 107062306a36Sopenharmony_ci } while (!atomic_long_try_cmpxchg(&data_ring->head_lpos, &begin_lpos, 107162306a36Sopenharmony_ci next_lpos)); /* LMM(data_alloc:A) */ 107262306a36Sopenharmony_ci 107362306a36Sopenharmony_ci blk = to_block(data_ring, begin_lpos); 107462306a36Sopenharmony_ci blk->id = id; /* LMM(data_alloc:B) */ 107562306a36Sopenharmony_ci 107662306a36Sopenharmony_ci if (DATA_WRAPS(data_ring, begin_lpos) != DATA_WRAPS(data_ring, next_lpos)) { 107762306a36Sopenharmony_ci /* Wrapping data blocks store their data at the beginning. */ 107862306a36Sopenharmony_ci blk = to_block(data_ring, 0); 107962306a36Sopenharmony_ci 108062306a36Sopenharmony_ci /* 108162306a36Sopenharmony_ci * Store the ID on the wrapped block for consistency. 108262306a36Sopenharmony_ci * The printk_ringbuffer does not actually use it. 108362306a36Sopenharmony_ci */ 108462306a36Sopenharmony_ci blk->id = id; 108562306a36Sopenharmony_ci } 108662306a36Sopenharmony_ci 108762306a36Sopenharmony_ci blk_lpos->begin = begin_lpos; 108862306a36Sopenharmony_ci blk_lpos->next = next_lpos; 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ci return &blk->data[0]; 109162306a36Sopenharmony_ci} 109262306a36Sopenharmony_ci 109362306a36Sopenharmony_ci/* 109462306a36Sopenharmony_ci * Try to resize an existing data block associated with the descriptor 109562306a36Sopenharmony_ci * specified by @id. If the resized data block should become wrapped, it 109662306a36Sopenharmony_ci * copies the old data to the new data block. If @size yields a data block 109762306a36Sopenharmony_ci * with the same or less size, the data block is left as is. 109862306a36Sopenharmony_ci * 109962306a36Sopenharmony_ci * Fail if this is not the last allocated data block or if there is not 110062306a36Sopenharmony_ci * enough space or it is not possible make enough space. 110162306a36Sopenharmony_ci * 110262306a36Sopenharmony_ci * Return a pointer to the beginning of the entire data buffer or NULL on 110362306a36Sopenharmony_ci * failure. 110462306a36Sopenharmony_ci */ 110562306a36Sopenharmony_cistatic char *data_realloc(struct printk_ringbuffer *rb, unsigned int size, 110662306a36Sopenharmony_ci struct prb_data_blk_lpos *blk_lpos, unsigned long id) 110762306a36Sopenharmony_ci{ 110862306a36Sopenharmony_ci struct prb_data_ring *data_ring = &rb->text_data_ring; 110962306a36Sopenharmony_ci struct prb_data_block *blk; 111062306a36Sopenharmony_ci unsigned long head_lpos; 111162306a36Sopenharmony_ci unsigned long next_lpos; 111262306a36Sopenharmony_ci bool wrapped; 111362306a36Sopenharmony_ci 111462306a36Sopenharmony_ci /* Reallocation only works if @blk_lpos is the newest data block. */ 111562306a36Sopenharmony_ci head_lpos = atomic_long_read(&data_ring->head_lpos); 111662306a36Sopenharmony_ci if (head_lpos != blk_lpos->next) 111762306a36Sopenharmony_ci return NULL; 111862306a36Sopenharmony_ci 111962306a36Sopenharmony_ci /* Keep track if @blk_lpos was a wrapping data block. */ 112062306a36Sopenharmony_ci wrapped = (DATA_WRAPS(data_ring, blk_lpos->begin) != DATA_WRAPS(data_ring, blk_lpos->next)); 112162306a36Sopenharmony_ci 112262306a36Sopenharmony_ci size = to_blk_size(size); 112362306a36Sopenharmony_ci 112462306a36Sopenharmony_ci next_lpos = get_next_lpos(data_ring, blk_lpos->begin, size); 112562306a36Sopenharmony_ci 112662306a36Sopenharmony_ci /* If the data block does not increase, there is nothing to do. */ 112762306a36Sopenharmony_ci if (head_lpos - next_lpos < DATA_SIZE(data_ring)) { 112862306a36Sopenharmony_ci if (wrapped) 112962306a36Sopenharmony_ci blk = to_block(data_ring, 0); 113062306a36Sopenharmony_ci else 113162306a36Sopenharmony_ci blk = to_block(data_ring, blk_lpos->begin); 113262306a36Sopenharmony_ci return &blk->data[0]; 113362306a36Sopenharmony_ci } 113462306a36Sopenharmony_ci 113562306a36Sopenharmony_ci if (!data_push_tail(rb, next_lpos - DATA_SIZE(data_ring))) 113662306a36Sopenharmony_ci return NULL; 113762306a36Sopenharmony_ci 113862306a36Sopenharmony_ci /* The memory barrier involvement is the same as data_alloc:A. */ 113962306a36Sopenharmony_ci if (!atomic_long_try_cmpxchg(&data_ring->head_lpos, &head_lpos, 114062306a36Sopenharmony_ci next_lpos)) { /* LMM(data_realloc:A) */ 114162306a36Sopenharmony_ci return NULL; 114262306a36Sopenharmony_ci } 114362306a36Sopenharmony_ci 114462306a36Sopenharmony_ci blk = to_block(data_ring, blk_lpos->begin); 114562306a36Sopenharmony_ci 114662306a36Sopenharmony_ci if (DATA_WRAPS(data_ring, blk_lpos->begin) != DATA_WRAPS(data_ring, next_lpos)) { 114762306a36Sopenharmony_ci struct prb_data_block *old_blk = blk; 114862306a36Sopenharmony_ci 114962306a36Sopenharmony_ci /* Wrapping data blocks store their data at the beginning. */ 115062306a36Sopenharmony_ci blk = to_block(data_ring, 0); 115162306a36Sopenharmony_ci 115262306a36Sopenharmony_ci /* 115362306a36Sopenharmony_ci * Store the ID on the wrapped block for consistency. 115462306a36Sopenharmony_ci * The printk_ringbuffer does not actually use it. 115562306a36Sopenharmony_ci */ 115662306a36Sopenharmony_ci blk->id = id; 115762306a36Sopenharmony_ci 115862306a36Sopenharmony_ci if (!wrapped) { 115962306a36Sopenharmony_ci /* 116062306a36Sopenharmony_ci * Since the allocated space is now in the newly 116162306a36Sopenharmony_ci * created wrapping data block, copy the content 116262306a36Sopenharmony_ci * from the old data block. 116362306a36Sopenharmony_ci */ 116462306a36Sopenharmony_ci memcpy(&blk->data[0], &old_blk->data[0], 116562306a36Sopenharmony_ci (blk_lpos->next - blk_lpos->begin) - sizeof(blk->id)); 116662306a36Sopenharmony_ci } 116762306a36Sopenharmony_ci } 116862306a36Sopenharmony_ci 116962306a36Sopenharmony_ci blk_lpos->next = next_lpos; 117062306a36Sopenharmony_ci 117162306a36Sopenharmony_ci return &blk->data[0]; 117262306a36Sopenharmony_ci} 117362306a36Sopenharmony_ci 117462306a36Sopenharmony_ci/* Return the number of bytes used by a data block. */ 117562306a36Sopenharmony_cistatic unsigned int space_used(struct prb_data_ring *data_ring, 117662306a36Sopenharmony_ci struct prb_data_blk_lpos *blk_lpos) 117762306a36Sopenharmony_ci{ 117862306a36Sopenharmony_ci /* Data-less blocks take no space. */ 117962306a36Sopenharmony_ci if (BLK_DATALESS(blk_lpos)) 118062306a36Sopenharmony_ci return 0; 118162306a36Sopenharmony_ci 118262306a36Sopenharmony_ci if (DATA_WRAPS(data_ring, blk_lpos->begin) == DATA_WRAPS(data_ring, blk_lpos->next)) { 118362306a36Sopenharmony_ci /* Data block does not wrap. */ 118462306a36Sopenharmony_ci return (DATA_INDEX(data_ring, blk_lpos->next) - 118562306a36Sopenharmony_ci DATA_INDEX(data_ring, blk_lpos->begin)); 118662306a36Sopenharmony_ci } 118762306a36Sopenharmony_ci 118862306a36Sopenharmony_ci /* 118962306a36Sopenharmony_ci * For wrapping data blocks, the trailing (wasted) space is 119062306a36Sopenharmony_ci * also counted. 119162306a36Sopenharmony_ci */ 119262306a36Sopenharmony_ci return (DATA_INDEX(data_ring, blk_lpos->next) + 119362306a36Sopenharmony_ci DATA_SIZE(data_ring) - DATA_INDEX(data_ring, blk_lpos->begin)); 119462306a36Sopenharmony_ci} 119562306a36Sopenharmony_ci 119662306a36Sopenharmony_ci/* 119762306a36Sopenharmony_ci * Given @blk_lpos, return a pointer to the writer data from the data block 119862306a36Sopenharmony_ci * and calculate the size of the data part. A NULL pointer is returned if 119962306a36Sopenharmony_ci * @blk_lpos specifies values that could never be legal. 120062306a36Sopenharmony_ci * 120162306a36Sopenharmony_ci * This function (used by readers) performs strict validation on the lpos 120262306a36Sopenharmony_ci * values to possibly detect bugs in the writer code. A WARN_ON_ONCE() is 120362306a36Sopenharmony_ci * triggered if an internal error is detected. 120462306a36Sopenharmony_ci */ 120562306a36Sopenharmony_cistatic const char *get_data(struct prb_data_ring *data_ring, 120662306a36Sopenharmony_ci struct prb_data_blk_lpos *blk_lpos, 120762306a36Sopenharmony_ci unsigned int *data_size) 120862306a36Sopenharmony_ci{ 120962306a36Sopenharmony_ci struct prb_data_block *db; 121062306a36Sopenharmony_ci 121162306a36Sopenharmony_ci /* Data-less data block description. */ 121262306a36Sopenharmony_ci if (BLK_DATALESS(blk_lpos)) { 121362306a36Sopenharmony_ci if (blk_lpos->begin == NO_LPOS && blk_lpos->next == NO_LPOS) { 121462306a36Sopenharmony_ci *data_size = 0; 121562306a36Sopenharmony_ci return ""; 121662306a36Sopenharmony_ci } 121762306a36Sopenharmony_ci return NULL; 121862306a36Sopenharmony_ci } 121962306a36Sopenharmony_ci 122062306a36Sopenharmony_ci /* Regular data block: @begin less than @next and in same wrap. */ 122162306a36Sopenharmony_ci if (DATA_WRAPS(data_ring, blk_lpos->begin) == DATA_WRAPS(data_ring, blk_lpos->next) && 122262306a36Sopenharmony_ci blk_lpos->begin < blk_lpos->next) { 122362306a36Sopenharmony_ci db = to_block(data_ring, blk_lpos->begin); 122462306a36Sopenharmony_ci *data_size = blk_lpos->next - blk_lpos->begin; 122562306a36Sopenharmony_ci 122662306a36Sopenharmony_ci /* Wrapping data block: @begin is one wrap behind @next. */ 122762306a36Sopenharmony_ci } else if (DATA_WRAPS(data_ring, blk_lpos->begin + DATA_SIZE(data_ring)) == 122862306a36Sopenharmony_ci DATA_WRAPS(data_ring, blk_lpos->next)) { 122962306a36Sopenharmony_ci db = to_block(data_ring, 0); 123062306a36Sopenharmony_ci *data_size = DATA_INDEX(data_ring, blk_lpos->next); 123162306a36Sopenharmony_ci 123262306a36Sopenharmony_ci /* Illegal block description. */ 123362306a36Sopenharmony_ci } else { 123462306a36Sopenharmony_ci WARN_ON_ONCE(1); 123562306a36Sopenharmony_ci return NULL; 123662306a36Sopenharmony_ci } 123762306a36Sopenharmony_ci 123862306a36Sopenharmony_ci /* A valid data block will always be aligned to the ID size. */ 123962306a36Sopenharmony_ci if (WARN_ON_ONCE(blk_lpos->begin != ALIGN(blk_lpos->begin, sizeof(db->id))) || 124062306a36Sopenharmony_ci WARN_ON_ONCE(blk_lpos->next != ALIGN(blk_lpos->next, sizeof(db->id)))) { 124162306a36Sopenharmony_ci return NULL; 124262306a36Sopenharmony_ci } 124362306a36Sopenharmony_ci 124462306a36Sopenharmony_ci /* A valid data block will always have at least an ID. */ 124562306a36Sopenharmony_ci if (WARN_ON_ONCE(*data_size < sizeof(db->id))) 124662306a36Sopenharmony_ci return NULL; 124762306a36Sopenharmony_ci 124862306a36Sopenharmony_ci /* Subtract block ID space from size to reflect data size. */ 124962306a36Sopenharmony_ci *data_size -= sizeof(db->id); 125062306a36Sopenharmony_ci 125162306a36Sopenharmony_ci return &db->data[0]; 125262306a36Sopenharmony_ci} 125362306a36Sopenharmony_ci 125462306a36Sopenharmony_ci/* 125562306a36Sopenharmony_ci * Attempt to transition the newest descriptor from committed back to reserved 125662306a36Sopenharmony_ci * so that the record can be modified by a writer again. This is only possible 125762306a36Sopenharmony_ci * if the descriptor is not yet finalized and the provided @caller_id matches. 125862306a36Sopenharmony_ci */ 125962306a36Sopenharmony_cistatic struct prb_desc *desc_reopen_last(struct prb_desc_ring *desc_ring, 126062306a36Sopenharmony_ci u32 caller_id, unsigned long *id_out) 126162306a36Sopenharmony_ci{ 126262306a36Sopenharmony_ci unsigned long prev_state_val; 126362306a36Sopenharmony_ci enum desc_state d_state; 126462306a36Sopenharmony_ci struct prb_desc desc; 126562306a36Sopenharmony_ci struct prb_desc *d; 126662306a36Sopenharmony_ci unsigned long id; 126762306a36Sopenharmony_ci u32 cid; 126862306a36Sopenharmony_ci 126962306a36Sopenharmony_ci id = atomic_long_read(&desc_ring->head_id); 127062306a36Sopenharmony_ci 127162306a36Sopenharmony_ci /* 127262306a36Sopenharmony_ci * To reduce unnecessarily reopening, first check if the descriptor 127362306a36Sopenharmony_ci * state and caller ID are correct. 127462306a36Sopenharmony_ci */ 127562306a36Sopenharmony_ci d_state = desc_read(desc_ring, id, &desc, NULL, &cid); 127662306a36Sopenharmony_ci if (d_state != desc_committed || cid != caller_id) 127762306a36Sopenharmony_ci return NULL; 127862306a36Sopenharmony_ci 127962306a36Sopenharmony_ci d = to_desc(desc_ring, id); 128062306a36Sopenharmony_ci 128162306a36Sopenharmony_ci prev_state_val = DESC_SV(id, desc_committed); 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_ci /* 128462306a36Sopenharmony_ci * Guarantee the reserved state is stored before reading any 128562306a36Sopenharmony_ci * record data. A full memory barrier is needed because @state_var 128662306a36Sopenharmony_ci * modification is followed by reading. This pairs with _prb_commit:B. 128762306a36Sopenharmony_ci * 128862306a36Sopenharmony_ci * Memory barrier involvement: 128962306a36Sopenharmony_ci * 129062306a36Sopenharmony_ci * If desc_reopen_last:A reads from _prb_commit:B, then 129162306a36Sopenharmony_ci * prb_reserve_in_last:A reads from _prb_commit:A. 129262306a36Sopenharmony_ci * 129362306a36Sopenharmony_ci * Relies on: 129462306a36Sopenharmony_ci * 129562306a36Sopenharmony_ci * WMB from _prb_commit:A to _prb_commit:B 129662306a36Sopenharmony_ci * matching 129762306a36Sopenharmony_ci * MB If desc_reopen_last:A to prb_reserve_in_last:A 129862306a36Sopenharmony_ci */ 129962306a36Sopenharmony_ci if (!atomic_long_try_cmpxchg(&d->state_var, &prev_state_val, 130062306a36Sopenharmony_ci DESC_SV(id, desc_reserved))) { /* LMM(desc_reopen_last:A) */ 130162306a36Sopenharmony_ci return NULL; 130262306a36Sopenharmony_ci } 130362306a36Sopenharmony_ci 130462306a36Sopenharmony_ci *id_out = id; 130562306a36Sopenharmony_ci return d; 130662306a36Sopenharmony_ci} 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_ci/** 130962306a36Sopenharmony_ci * prb_reserve_in_last() - Re-reserve and extend the space in the ringbuffer 131062306a36Sopenharmony_ci * used by the newest record. 131162306a36Sopenharmony_ci * 131262306a36Sopenharmony_ci * @e: The entry structure to setup. 131362306a36Sopenharmony_ci * @rb: The ringbuffer to re-reserve and extend data in. 131462306a36Sopenharmony_ci * @r: The record structure to allocate buffers for. 131562306a36Sopenharmony_ci * @caller_id: The caller ID of the caller (reserving writer). 131662306a36Sopenharmony_ci * @max_size: Fail if the extended size would be greater than this. 131762306a36Sopenharmony_ci * 131862306a36Sopenharmony_ci * This is the public function available to writers to re-reserve and extend 131962306a36Sopenharmony_ci * data. 132062306a36Sopenharmony_ci * 132162306a36Sopenharmony_ci * The writer specifies the text size to extend (not the new total size) by 132262306a36Sopenharmony_ci * setting the @text_buf_size field of @r. To ensure proper initialization 132362306a36Sopenharmony_ci * of @r, prb_rec_init_wr() should be used. 132462306a36Sopenharmony_ci * 132562306a36Sopenharmony_ci * This function will fail if @caller_id does not match the caller ID of the 132662306a36Sopenharmony_ci * newest record. In that case the caller must reserve new data using 132762306a36Sopenharmony_ci * prb_reserve(). 132862306a36Sopenharmony_ci * 132962306a36Sopenharmony_ci * Context: Any context. Disables local interrupts on success. 133062306a36Sopenharmony_ci * Return: true if text data could be extended, otherwise false. 133162306a36Sopenharmony_ci * 133262306a36Sopenharmony_ci * On success: 133362306a36Sopenharmony_ci * 133462306a36Sopenharmony_ci * - @r->text_buf points to the beginning of the entire text buffer. 133562306a36Sopenharmony_ci * 133662306a36Sopenharmony_ci * - @r->text_buf_size is set to the new total size of the buffer. 133762306a36Sopenharmony_ci * 133862306a36Sopenharmony_ci * - @r->info is not touched so that @r->info->text_len could be used 133962306a36Sopenharmony_ci * to append the text. 134062306a36Sopenharmony_ci * 134162306a36Sopenharmony_ci * - prb_record_text_space() can be used on @e to query the new 134262306a36Sopenharmony_ci * actually used space. 134362306a36Sopenharmony_ci * 134462306a36Sopenharmony_ci * Important: All @r->info fields will already be set with the current values 134562306a36Sopenharmony_ci * for the record. I.e. @r->info->text_len will be less than 134662306a36Sopenharmony_ci * @text_buf_size. Writers can use @r->info->text_len to know 134762306a36Sopenharmony_ci * where concatenation begins and writers should update 134862306a36Sopenharmony_ci * @r->info->text_len after concatenating. 134962306a36Sopenharmony_ci */ 135062306a36Sopenharmony_cibool prb_reserve_in_last(struct prb_reserved_entry *e, struct printk_ringbuffer *rb, 135162306a36Sopenharmony_ci struct printk_record *r, u32 caller_id, unsigned int max_size) 135262306a36Sopenharmony_ci{ 135362306a36Sopenharmony_ci struct prb_desc_ring *desc_ring = &rb->desc_ring; 135462306a36Sopenharmony_ci struct printk_info *info; 135562306a36Sopenharmony_ci unsigned int data_size; 135662306a36Sopenharmony_ci struct prb_desc *d; 135762306a36Sopenharmony_ci unsigned long id; 135862306a36Sopenharmony_ci 135962306a36Sopenharmony_ci local_irq_save(e->irqflags); 136062306a36Sopenharmony_ci 136162306a36Sopenharmony_ci /* Transition the newest descriptor back to the reserved state. */ 136262306a36Sopenharmony_ci d = desc_reopen_last(desc_ring, caller_id, &id); 136362306a36Sopenharmony_ci if (!d) { 136462306a36Sopenharmony_ci local_irq_restore(e->irqflags); 136562306a36Sopenharmony_ci goto fail_reopen; 136662306a36Sopenharmony_ci } 136762306a36Sopenharmony_ci 136862306a36Sopenharmony_ci /* Now the writer has exclusive access: LMM(prb_reserve_in_last:A) */ 136962306a36Sopenharmony_ci 137062306a36Sopenharmony_ci info = to_info(desc_ring, id); 137162306a36Sopenharmony_ci 137262306a36Sopenharmony_ci /* 137362306a36Sopenharmony_ci * Set the @e fields here so that prb_commit() can be used if 137462306a36Sopenharmony_ci * anything fails from now on. 137562306a36Sopenharmony_ci */ 137662306a36Sopenharmony_ci e->rb = rb; 137762306a36Sopenharmony_ci e->id = id; 137862306a36Sopenharmony_ci 137962306a36Sopenharmony_ci /* 138062306a36Sopenharmony_ci * desc_reopen_last() checked the caller_id, but there was no 138162306a36Sopenharmony_ci * exclusive access at that point. The descriptor may have 138262306a36Sopenharmony_ci * changed since then. 138362306a36Sopenharmony_ci */ 138462306a36Sopenharmony_ci if (caller_id != info->caller_id) 138562306a36Sopenharmony_ci goto fail; 138662306a36Sopenharmony_ci 138762306a36Sopenharmony_ci if (BLK_DATALESS(&d->text_blk_lpos)) { 138862306a36Sopenharmony_ci if (WARN_ON_ONCE(info->text_len != 0)) { 138962306a36Sopenharmony_ci pr_warn_once("wrong text_len value (%hu, expecting 0)\n", 139062306a36Sopenharmony_ci info->text_len); 139162306a36Sopenharmony_ci info->text_len = 0; 139262306a36Sopenharmony_ci } 139362306a36Sopenharmony_ci 139462306a36Sopenharmony_ci if (!data_check_size(&rb->text_data_ring, r->text_buf_size)) 139562306a36Sopenharmony_ci goto fail; 139662306a36Sopenharmony_ci 139762306a36Sopenharmony_ci if (r->text_buf_size > max_size) 139862306a36Sopenharmony_ci goto fail; 139962306a36Sopenharmony_ci 140062306a36Sopenharmony_ci r->text_buf = data_alloc(rb, r->text_buf_size, 140162306a36Sopenharmony_ci &d->text_blk_lpos, id); 140262306a36Sopenharmony_ci } else { 140362306a36Sopenharmony_ci if (!get_data(&rb->text_data_ring, &d->text_blk_lpos, &data_size)) 140462306a36Sopenharmony_ci goto fail; 140562306a36Sopenharmony_ci 140662306a36Sopenharmony_ci /* 140762306a36Sopenharmony_ci * Increase the buffer size to include the original size. If 140862306a36Sopenharmony_ci * the meta data (@text_len) is not sane, use the full data 140962306a36Sopenharmony_ci * block size. 141062306a36Sopenharmony_ci */ 141162306a36Sopenharmony_ci if (WARN_ON_ONCE(info->text_len > data_size)) { 141262306a36Sopenharmony_ci pr_warn_once("wrong text_len value (%hu, expecting <=%u)\n", 141362306a36Sopenharmony_ci info->text_len, data_size); 141462306a36Sopenharmony_ci info->text_len = data_size; 141562306a36Sopenharmony_ci } 141662306a36Sopenharmony_ci r->text_buf_size += info->text_len; 141762306a36Sopenharmony_ci 141862306a36Sopenharmony_ci if (!data_check_size(&rb->text_data_ring, r->text_buf_size)) 141962306a36Sopenharmony_ci goto fail; 142062306a36Sopenharmony_ci 142162306a36Sopenharmony_ci if (r->text_buf_size > max_size) 142262306a36Sopenharmony_ci goto fail; 142362306a36Sopenharmony_ci 142462306a36Sopenharmony_ci r->text_buf = data_realloc(rb, r->text_buf_size, 142562306a36Sopenharmony_ci &d->text_blk_lpos, id); 142662306a36Sopenharmony_ci } 142762306a36Sopenharmony_ci if (r->text_buf_size && !r->text_buf) 142862306a36Sopenharmony_ci goto fail; 142962306a36Sopenharmony_ci 143062306a36Sopenharmony_ci r->info = info; 143162306a36Sopenharmony_ci 143262306a36Sopenharmony_ci e->text_space = space_used(&rb->text_data_ring, &d->text_blk_lpos); 143362306a36Sopenharmony_ci 143462306a36Sopenharmony_ci return true; 143562306a36Sopenharmony_cifail: 143662306a36Sopenharmony_ci prb_commit(e); 143762306a36Sopenharmony_ci /* prb_commit() re-enabled interrupts. */ 143862306a36Sopenharmony_cifail_reopen: 143962306a36Sopenharmony_ci /* Make it clear to the caller that the re-reserve failed. */ 144062306a36Sopenharmony_ci memset(r, 0, sizeof(*r)); 144162306a36Sopenharmony_ci return false; 144262306a36Sopenharmony_ci} 144362306a36Sopenharmony_ci 144462306a36Sopenharmony_ci/* 144562306a36Sopenharmony_ci * Attempt to finalize a specified descriptor. If this fails, the descriptor 144662306a36Sopenharmony_ci * is either already final or it will finalize itself when the writer commits. 144762306a36Sopenharmony_ci */ 144862306a36Sopenharmony_cistatic void desc_make_final(struct prb_desc_ring *desc_ring, unsigned long id) 144962306a36Sopenharmony_ci{ 145062306a36Sopenharmony_ci unsigned long prev_state_val = DESC_SV(id, desc_committed); 145162306a36Sopenharmony_ci struct prb_desc *d = to_desc(desc_ring, id); 145262306a36Sopenharmony_ci 145362306a36Sopenharmony_ci atomic_long_cmpxchg_relaxed(&d->state_var, prev_state_val, 145462306a36Sopenharmony_ci DESC_SV(id, desc_finalized)); /* LMM(desc_make_final:A) */ 145562306a36Sopenharmony_ci 145662306a36Sopenharmony_ci /* Best effort to remember the last finalized @id. */ 145762306a36Sopenharmony_ci atomic_long_set(&desc_ring->last_finalized_id, id); 145862306a36Sopenharmony_ci} 145962306a36Sopenharmony_ci 146062306a36Sopenharmony_ci/** 146162306a36Sopenharmony_ci * prb_reserve() - Reserve space in the ringbuffer. 146262306a36Sopenharmony_ci * 146362306a36Sopenharmony_ci * @e: The entry structure to setup. 146462306a36Sopenharmony_ci * @rb: The ringbuffer to reserve data in. 146562306a36Sopenharmony_ci * @r: The record structure to allocate buffers for. 146662306a36Sopenharmony_ci * 146762306a36Sopenharmony_ci * This is the public function available to writers to reserve data. 146862306a36Sopenharmony_ci * 146962306a36Sopenharmony_ci * The writer specifies the text size to reserve by setting the 147062306a36Sopenharmony_ci * @text_buf_size field of @r. To ensure proper initialization of @r, 147162306a36Sopenharmony_ci * prb_rec_init_wr() should be used. 147262306a36Sopenharmony_ci * 147362306a36Sopenharmony_ci * Context: Any context. Disables local interrupts on success. 147462306a36Sopenharmony_ci * Return: true if at least text data could be allocated, otherwise false. 147562306a36Sopenharmony_ci * 147662306a36Sopenharmony_ci * On success, the fields @info and @text_buf of @r will be set by this 147762306a36Sopenharmony_ci * function and should be filled in by the writer before committing. Also 147862306a36Sopenharmony_ci * on success, prb_record_text_space() can be used on @e to query the actual 147962306a36Sopenharmony_ci * space used for the text data block. 148062306a36Sopenharmony_ci * 148162306a36Sopenharmony_ci * Important: @info->text_len needs to be set correctly by the writer in 148262306a36Sopenharmony_ci * order for data to be readable and/or extended. Its value 148362306a36Sopenharmony_ci * is initialized to 0. 148462306a36Sopenharmony_ci */ 148562306a36Sopenharmony_cibool prb_reserve(struct prb_reserved_entry *e, struct printk_ringbuffer *rb, 148662306a36Sopenharmony_ci struct printk_record *r) 148762306a36Sopenharmony_ci{ 148862306a36Sopenharmony_ci struct prb_desc_ring *desc_ring = &rb->desc_ring; 148962306a36Sopenharmony_ci struct printk_info *info; 149062306a36Sopenharmony_ci struct prb_desc *d; 149162306a36Sopenharmony_ci unsigned long id; 149262306a36Sopenharmony_ci u64 seq; 149362306a36Sopenharmony_ci 149462306a36Sopenharmony_ci if (!data_check_size(&rb->text_data_ring, r->text_buf_size)) 149562306a36Sopenharmony_ci goto fail; 149662306a36Sopenharmony_ci 149762306a36Sopenharmony_ci /* 149862306a36Sopenharmony_ci * Descriptors in the reserved state act as blockers to all further 149962306a36Sopenharmony_ci * reservations once the desc_ring has fully wrapped. Disable 150062306a36Sopenharmony_ci * interrupts during the reserve/commit window in order to minimize 150162306a36Sopenharmony_ci * the likelihood of this happening. 150262306a36Sopenharmony_ci */ 150362306a36Sopenharmony_ci local_irq_save(e->irqflags); 150462306a36Sopenharmony_ci 150562306a36Sopenharmony_ci if (!desc_reserve(rb, &id)) { 150662306a36Sopenharmony_ci /* Descriptor reservation failures are tracked. */ 150762306a36Sopenharmony_ci atomic_long_inc(&rb->fail); 150862306a36Sopenharmony_ci local_irq_restore(e->irqflags); 150962306a36Sopenharmony_ci goto fail; 151062306a36Sopenharmony_ci } 151162306a36Sopenharmony_ci 151262306a36Sopenharmony_ci d = to_desc(desc_ring, id); 151362306a36Sopenharmony_ci info = to_info(desc_ring, id); 151462306a36Sopenharmony_ci 151562306a36Sopenharmony_ci /* 151662306a36Sopenharmony_ci * All @info fields (except @seq) are cleared and must be filled in 151762306a36Sopenharmony_ci * by the writer. Save @seq before clearing because it is used to 151862306a36Sopenharmony_ci * determine the new sequence number. 151962306a36Sopenharmony_ci */ 152062306a36Sopenharmony_ci seq = info->seq; 152162306a36Sopenharmony_ci memset(info, 0, sizeof(*info)); 152262306a36Sopenharmony_ci 152362306a36Sopenharmony_ci /* 152462306a36Sopenharmony_ci * Set the @e fields here so that prb_commit() can be used if 152562306a36Sopenharmony_ci * text data allocation fails. 152662306a36Sopenharmony_ci */ 152762306a36Sopenharmony_ci e->rb = rb; 152862306a36Sopenharmony_ci e->id = id; 152962306a36Sopenharmony_ci 153062306a36Sopenharmony_ci /* 153162306a36Sopenharmony_ci * Initialize the sequence number if it has "never been set". 153262306a36Sopenharmony_ci * Otherwise just increment it by a full wrap. 153362306a36Sopenharmony_ci * 153462306a36Sopenharmony_ci * @seq is considered "never been set" if it has a value of 0, 153562306a36Sopenharmony_ci * _except_ for @infos[0], which was specially setup by the ringbuffer 153662306a36Sopenharmony_ci * initializer and therefore is always considered as set. 153762306a36Sopenharmony_ci * 153862306a36Sopenharmony_ci * See the "Bootstrap" comment block in printk_ringbuffer.h for 153962306a36Sopenharmony_ci * details about how the initializer bootstraps the descriptors. 154062306a36Sopenharmony_ci */ 154162306a36Sopenharmony_ci if (seq == 0 && DESC_INDEX(desc_ring, id) != 0) 154262306a36Sopenharmony_ci info->seq = DESC_INDEX(desc_ring, id); 154362306a36Sopenharmony_ci else 154462306a36Sopenharmony_ci info->seq = seq + DESCS_COUNT(desc_ring); 154562306a36Sopenharmony_ci 154662306a36Sopenharmony_ci /* 154762306a36Sopenharmony_ci * New data is about to be reserved. Once that happens, previous 154862306a36Sopenharmony_ci * descriptors are no longer able to be extended. Finalize the 154962306a36Sopenharmony_ci * previous descriptor now so that it can be made available to 155062306a36Sopenharmony_ci * readers. (For seq==0 there is no previous descriptor.) 155162306a36Sopenharmony_ci */ 155262306a36Sopenharmony_ci if (info->seq > 0) 155362306a36Sopenharmony_ci desc_make_final(desc_ring, DESC_ID(id - 1)); 155462306a36Sopenharmony_ci 155562306a36Sopenharmony_ci r->text_buf = data_alloc(rb, r->text_buf_size, &d->text_blk_lpos, id); 155662306a36Sopenharmony_ci /* If text data allocation fails, a data-less record is committed. */ 155762306a36Sopenharmony_ci if (r->text_buf_size && !r->text_buf) { 155862306a36Sopenharmony_ci prb_commit(e); 155962306a36Sopenharmony_ci /* prb_commit() re-enabled interrupts. */ 156062306a36Sopenharmony_ci goto fail; 156162306a36Sopenharmony_ci } 156262306a36Sopenharmony_ci 156362306a36Sopenharmony_ci r->info = info; 156462306a36Sopenharmony_ci 156562306a36Sopenharmony_ci /* Record full text space used by record. */ 156662306a36Sopenharmony_ci e->text_space = space_used(&rb->text_data_ring, &d->text_blk_lpos); 156762306a36Sopenharmony_ci 156862306a36Sopenharmony_ci return true; 156962306a36Sopenharmony_cifail: 157062306a36Sopenharmony_ci /* Make it clear to the caller that the reserve failed. */ 157162306a36Sopenharmony_ci memset(r, 0, sizeof(*r)); 157262306a36Sopenharmony_ci return false; 157362306a36Sopenharmony_ci} 157462306a36Sopenharmony_ci 157562306a36Sopenharmony_ci/* Commit the data (possibly finalizing it) and restore interrupts. */ 157662306a36Sopenharmony_cistatic void _prb_commit(struct prb_reserved_entry *e, unsigned long state_val) 157762306a36Sopenharmony_ci{ 157862306a36Sopenharmony_ci struct prb_desc_ring *desc_ring = &e->rb->desc_ring; 157962306a36Sopenharmony_ci struct prb_desc *d = to_desc(desc_ring, e->id); 158062306a36Sopenharmony_ci unsigned long prev_state_val = DESC_SV(e->id, desc_reserved); 158162306a36Sopenharmony_ci 158262306a36Sopenharmony_ci /* Now the writer has finished all writing: LMM(_prb_commit:A) */ 158362306a36Sopenharmony_ci 158462306a36Sopenharmony_ci /* 158562306a36Sopenharmony_ci * Set the descriptor as committed. See "ABA Issues" about why 158662306a36Sopenharmony_ci * cmpxchg() instead of set() is used. 158762306a36Sopenharmony_ci * 158862306a36Sopenharmony_ci * 1 Guarantee all record data is stored before the descriptor state 158962306a36Sopenharmony_ci * is stored as committed. A write memory barrier is sufficient 159062306a36Sopenharmony_ci * for this. This pairs with desc_read:B and desc_reopen_last:A. 159162306a36Sopenharmony_ci * 159262306a36Sopenharmony_ci * 2. Guarantee the descriptor state is stored as committed before 159362306a36Sopenharmony_ci * re-checking the head ID in order to possibly finalize this 159462306a36Sopenharmony_ci * descriptor. This pairs with desc_reserve:D. 159562306a36Sopenharmony_ci * 159662306a36Sopenharmony_ci * Memory barrier involvement: 159762306a36Sopenharmony_ci * 159862306a36Sopenharmony_ci * If prb_commit:A reads from desc_reserve:D, then 159962306a36Sopenharmony_ci * desc_make_final:A reads from _prb_commit:B. 160062306a36Sopenharmony_ci * 160162306a36Sopenharmony_ci * Relies on: 160262306a36Sopenharmony_ci * 160362306a36Sopenharmony_ci * MB _prb_commit:B to prb_commit:A 160462306a36Sopenharmony_ci * matching 160562306a36Sopenharmony_ci * MB desc_reserve:D to desc_make_final:A 160662306a36Sopenharmony_ci */ 160762306a36Sopenharmony_ci if (!atomic_long_try_cmpxchg(&d->state_var, &prev_state_val, 160862306a36Sopenharmony_ci DESC_SV(e->id, state_val))) { /* LMM(_prb_commit:B) */ 160962306a36Sopenharmony_ci WARN_ON_ONCE(1); 161062306a36Sopenharmony_ci } 161162306a36Sopenharmony_ci 161262306a36Sopenharmony_ci /* Restore interrupts, the reserve/commit window is finished. */ 161362306a36Sopenharmony_ci local_irq_restore(e->irqflags); 161462306a36Sopenharmony_ci} 161562306a36Sopenharmony_ci 161662306a36Sopenharmony_ci/** 161762306a36Sopenharmony_ci * prb_commit() - Commit (previously reserved) data to the ringbuffer. 161862306a36Sopenharmony_ci * 161962306a36Sopenharmony_ci * @e: The entry containing the reserved data information. 162062306a36Sopenharmony_ci * 162162306a36Sopenharmony_ci * This is the public function available to writers to commit data. 162262306a36Sopenharmony_ci * 162362306a36Sopenharmony_ci * Note that the data is not yet available to readers until it is finalized. 162462306a36Sopenharmony_ci * Finalizing happens automatically when space for the next record is 162562306a36Sopenharmony_ci * reserved. 162662306a36Sopenharmony_ci * 162762306a36Sopenharmony_ci * See prb_final_commit() for a version of this function that finalizes 162862306a36Sopenharmony_ci * immediately. 162962306a36Sopenharmony_ci * 163062306a36Sopenharmony_ci * Context: Any context. Enables local interrupts. 163162306a36Sopenharmony_ci */ 163262306a36Sopenharmony_civoid prb_commit(struct prb_reserved_entry *e) 163362306a36Sopenharmony_ci{ 163462306a36Sopenharmony_ci struct prb_desc_ring *desc_ring = &e->rb->desc_ring; 163562306a36Sopenharmony_ci unsigned long head_id; 163662306a36Sopenharmony_ci 163762306a36Sopenharmony_ci _prb_commit(e, desc_committed); 163862306a36Sopenharmony_ci 163962306a36Sopenharmony_ci /* 164062306a36Sopenharmony_ci * If this descriptor is no longer the head (i.e. a new record has 164162306a36Sopenharmony_ci * been allocated), extending the data for this record is no longer 164262306a36Sopenharmony_ci * allowed and therefore it must be finalized. 164362306a36Sopenharmony_ci */ 164462306a36Sopenharmony_ci head_id = atomic_long_read(&desc_ring->head_id); /* LMM(prb_commit:A) */ 164562306a36Sopenharmony_ci if (head_id != e->id) 164662306a36Sopenharmony_ci desc_make_final(desc_ring, e->id); 164762306a36Sopenharmony_ci} 164862306a36Sopenharmony_ci 164962306a36Sopenharmony_ci/** 165062306a36Sopenharmony_ci * prb_final_commit() - Commit and finalize (previously reserved) data to 165162306a36Sopenharmony_ci * the ringbuffer. 165262306a36Sopenharmony_ci * 165362306a36Sopenharmony_ci * @e: The entry containing the reserved data information. 165462306a36Sopenharmony_ci * 165562306a36Sopenharmony_ci * This is the public function available to writers to commit+finalize data. 165662306a36Sopenharmony_ci * 165762306a36Sopenharmony_ci * By finalizing, the data is made immediately available to readers. 165862306a36Sopenharmony_ci * 165962306a36Sopenharmony_ci * This function should only be used if there are no intentions of extending 166062306a36Sopenharmony_ci * this data using prb_reserve_in_last(). 166162306a36Sopenharmony_ci * 166262306a36Sopenharmony_ci * Context: Any context. Enables local interrupts. 166362306a36Sopenharmony_ci */ 166462306a36Sopenharmony_civoid prb_final_commit(struct prb_reserved_entry *e) 166562306a36Sopenharmony_ci{ 166662306a36Sopenharmony_ci struct prb_desc_ring *desc_ring = &e->rb->desc_ring; 166762306a36Sopenharmony_ci 166862306a36Sopenharmony_ci _prb_commit(e, desc_finalized); 166962306a36Sopenharmony_ci 167062306a36Sopenharmony_ci /* Best effort to remember the last finalized @id. */ 167162306a36Sopenharmony_ci atomic_long_set(&desc_ring->last_finalized_id, e->id); 167262306a36Sopenharmony_ci} 167362306a36Sopenharmony_ci 167462306a36Sopenharmony_ci/* 167562306a36Sopenharmony_ci * Count the number of lines in provided text. All text has at least 1 line 167662306a36Sopenharmony_ci * (even if @text_size is 0). Each '\n' processed is counted as an additional 167762306a36Sopenharmony_ci * line. 167862306a36Sopenharmony_ci */ 167962306a36Sopenharmony_cistatic unsigned int count_lines(const char *text, unsigned int text_size) 168062306a36Sopenharmony_ci{ 168162306a36Sopenharmony_ci unsigned int next_size = text_size; 168262306a36Sopenharmony_ci unsigned int line_count = 1; 168362306a36Sopenharmony_ci const char *next = text; 168462306a36Sopenharmony_ci 168562306a36Sopenharmony_ci while (next_size) { 168662306a36Sopenharmony_ci next = memchr(next, '\n', next_size); 168762306a36Sopenharmony_ci if (!next) 168862306a36Sopenharmony_ci break; 168962306a36Sopenharmony_ci line_count++; 169062306a36Sopenharmony_ci next++; 169162306a36Sopenharmony_ci next_size = text_size - (next - text); 169262306a36Sopenharmony_ci } 169362306a36Sopenharmony_ci 169462306a36Sopenharmony_ci return line_count; 169562306a36Sopenharmony_ci} 169662306a36Sopenharmony_ci 169762306a36Sopenharmony_ci/* 169862306a36Sopenharmony_ci * Given @blk_lpos, copy an expected @len of data into the provided buffer. 169962306a36Sopenharmony_ci * If @line_count is provided, count the number of lines in the data. 170062306a36Sopenharmony_ci * 170162306a36Sopenharmony_ci * This function (used by readers) performs strict validation on the data 170262306a36Sopenharmony_ci * size to possibly detect bugs in the writer code. A WARN_ON_ONCE() is 170362306a36Sopenharmony_ci * triggered if an internal error is detected. 170462306a36Sopenharmony_ci */ 170562306a36Sopenharmony_cistatic bool copy_data(struct prb_data_ring *data_ring, 170662306a36Sopenharmony_ci struct prb_data_blk_lpos *blk_lpos, u16 len, char *buf, 170762306a36Sopenharmony_ci unsigned int buf_size, unsigned int *line_count) 170862306a36Sopenharmony_ci{ 170962306a36Sopenharmony_ci unsigned int data_size; 171062306a36Sopenharmony_ci const char *data; 171162306a36Sopenharmony_ci 171262306a36Sopenharmony_ci /* Caller might not want any data. */ 171362306a36Sopenharmony_ci if ((!buf || !buf_size) && !line_count) 171462306a36Sopenharmony_ci return true; 171562306a36Sopenharmony_ci 171662306a36Sopenharmony_ci data = get_data(data_ring, blk_lpos, &data_size); 171762306a36Sopenharmony_ci if (!data) 171862306a36Sopenharmony_ci return false; 171962306a36Sopenharmony_ci 172062306a36Sopenharmony_ci /* 172162306a36Sopenharmony_ci * Actual cannot be less than expected. It can be more than expected 172262306a36Sopenharmony_ci * because of the trailing alignment padding. 172362306a36Sopenharmony_ci * 172462306a36Sopenharmony_ci * Note that invalid @len values can occur because the caller loads 172562306a36Sopenharmony_ci * the value during an allowed data race. 172662306a36Sopenharmony_ci */ 172762306a36Sopenharmony_ci if (data_size < (unsigned int)len) 172862306a36Sopenharmony_ci return false; 172962306a36Sopenharmony_ci 173062306a36Sopenharmony_ci /* Caller interested in the line count? */ 173162306a36Sopenharmony_ci if (line_count) 173262306a36Sopenharmony_ci *line_count = count_lines(data, len); 173362306a36Sopenharmony_ci 173462306a36Sopenharmony_ci /* Caller interested in the data content? */ 173562306a36Sopenharmony_ci if (!buf || !buf_size) 173662306a36Sopenharmony_ci return true; 173762306a36Sopenharmony_ci 173862306a36Sopenharmony_ci data_size = min_t(unsigned int, buf_size, len); 173962306a36Sopenharmony_ci 174062306a36Sopenharmony_ci memcpy(&buf[0], data, data_size); /* LMM(copy_data:A) */ 174162306a36Sopenharmony_ci return true; 174262306a36Sopenharmony_ci} 174362306a36Sopenharmony_ci 174462306a36Sopenharmony_ci/* 174562306a36Sopenharmony_ci * This is an extended version of desc_read(). It gets a copy of a specified 174662306a36Sopenharmony_ci * descriptor. However, it also verifies that the record is finalized and has 174762306a36Sopenharmony_ci * the sequence number @seq. On success, 0 is returned. 174862306a36Sopenharmony_ci * 174962306a36Sopenharmony_ci * Error return values: 175062306a36Sopenharmony_ci * -EINVAL: A finalized record with sequence number @seq does not exist. 175162306a36Sopenharmony_ci * -ENOENT: A finalized record with sequence number @seq exists, but its data 175262306a36Sopenharmony_ci * is not available. This is a valid record, so readers should 175362306a36Sopenharmony_ci * continue with the next record. 175462306a36Sopenharmony_ci */ 175562306a36Sopenharmony_cistatic int desc_read_finalized_seq(struct prb_desc_ring *desc_ring, 175662306a36Sopenharmony_ci unsigned long id, u64 seq, 175762306a36Sopenharmony_ci struct prb_desc *desc_out) 175862306a36Sopenharmony_ci{ 175962306a36Sopenharmony_ci struct prb_data_blk_lpos *blk_lpos = &desc_out->text_blk_lpos; 176062306a36Sopenharmony_ci enum desc_state d_state; 176162306a36Sopenharmony_ci u64 s; 176262306a36Sopenharmony_ci 176362306a36Sopenharmony_ci d_state = desc_read(desc_ring, id, desc_out, &s, NULL); 176462306a36Sopenharmony_ci 176562306a36Sopenharmony_ci /* 176662306a36Sopenharmony_ci * An unexpected @id (desc_miss) or @seq mismatch means the record 176762306a36Sopenharmony_ci * does not exist. A descriptor in the reserved or committed state 176862306a36Sopenharmony_ci * means the record does not yet exist for the reader. 176962306a36Sopenharmony_ci */ 177062306a36Sopenharmony_ci if (d_state == desc_miss || 177162306a36Sopenharmony_ci d_state == desc_reserved || 177262306a36Sopenharmony_ci d_state == desc_committed || 177362306a36Sopenharmony_ci s != seq) { 177462306a36Sopenharmony_ci return -EINVAL; 177562306a36Sopenharmony_ci } 177662306a36Sopenharmony_ci 177762306a36Sopenharmony_ci /* 177862306a36Sopenharmony_ci * A descriptor in the reusable state may no longer have its data 177962306a36Sopenharmony_ci * available; report it as existing but with lost data. Or the record 178062306a36Sopenharmony_ci * may actually be a record with lost data. 178162306a36Sopenharmony_ci */ 178262306a36Sopenharmony_ci if (d_state == desc_reusable || 178362306a36Sopenharmony_ci (blk_lpos->begin == FAILED_LPOS && blk_lpos->next == FAILED_LPOS)) { 178462306a36Sopenharmony_ci return -ENOENT; 178562306a36Sopenharmony_ci } 178662306a36Sopenharmony_ci 178762306a36Sopenharmony_ci return 0; 178862306a36Sopenharmony_ci} 178962306a36Sopenharmony_ci 179062306a36Sopenharmony_ci/* 179162306a36Sopenharmony_ci * Copy the ringbuffer data from the record with @seq to the provided 179262306a36Sopenharmony_ci * @r buffer. On success, 0 is returned. 179362306a36Sopenharmony_ci * 179462306a36Sopenharmony_ci * See desc_read_finalized_seq() for error return values. 179562306a36Sopenharmony_ci */ 179662306a36Sopenharmony_cistatic int prb_read(struct printk_ringbuffer *rb, u64 seq, 179762306a36Sopenharmony_ci struct printk_record *r, unsigned int *line_count) 179862306a36Sopenharmony_ci{ 179962306a36Sopenharmony_ci struct prb_desc_ring *desc_ring = &rb->desc_ring; 180062306a36Sopenharmony_ci struct printk_info *info = to_info(desc_ring, seq); 180162306a36Sopenharmony_ci struct prb_desc *rdesc = to_desc(desc_ring, seq); 180262306a36Sopenharmony_ci atomic_long_t *state_var = &rdesc->state_var; 180362306a36Sopenharmony_ci struct prb_desc desc; 180462306a36Sopenharmony_ci unsigned long id; 180562306a36Sopenharmony_ci int err; 180662306a36Sopenharmony_ci 180762306a36Sopenharmony_ci /* Extract the ID, used to specify the descriptor to read. */ 180862306a36Sopenharmony_ci id = DESC_ID(atomic_long_read(state_var)); 180962306a36Sopenharmony_ci 181062306a36Sopenharmony_ci /* Get a local copy of the correct descriptor (if available). */ 181162306a36Sopenharmony_ci err = desc_read_finalized_seq(desc_ring, id, seq, &desc); 181262306a36Sopenharmony_ci 181362306a36Sopenharmony_ci /* 181462306a36Sopenharmony_ci * If @r is NULL, the caller is only interested in the availability 181562306a36Sopenharmony_ci * of the record. 181662306a36Sopenharmony_ci */ 181762306a36Sopenharmony_ci if (err || !r) 181862306a36Sopenharmony_ci return err; 181962306a36Sopenharmony_ci 182062306a36Sopenharmony_ci /* If requested, copy meta data. */ 182162306a36Sopenharmony_ci if (r->info) 182262306a36Sopenharmony_ci memcpy(r->info, info, sizeof(*(r->info))); 182362306a36Sopenharmony_ci 182462306a36Sopenharmony_ci /* Copy text data. If it fails, this is a data-less record. */ 182562306a36Sopenharmony_ci if (!copy_data(&rb->text_data_ring, &desc.text_blk_lpos, info->text_len, 182662306a36Sopenharmony_ci r->text_buf, r->text_buf_size, line_count)) { 182762306a36Sopenharmony_ci return -ENOENT; 182862306a36Sopenharmony_ci } 182962306a36Sopenharmony_ci 183062306a36Sopenharmony_ci /* Ensure the record is still finalized and has the same @seq. */ 183162306a36Sopenharmony_ci return desc_read_finalized_seq(desc_ring, id, seq, &desc); 183262306a36Sopenharmony_ci} 183362306a36Sopenharmony_ci 183462306a36Sopenharmony_ci/* Get the sequence number of the tail descriptor. */ 183562306a36Sopenharmony_cistatic u64 prb_first_seq(struct printk_ringbuffer *rb) 183662306a36Sopenharmony_ci{ 183762306a36Sopenharmony_ci struct prb_desc_ring *desc_ring = &rb->desc_ring; 183862306a36Sopenharmony_ci enum desc_state d_state; 183962306a36Sopenharmony_ci struct prb_desc desc; 184062306a36Sopenharmony_ci unsigned long id; 184162306a36Sopenharmony_ci u64 seq; 184262306a36Sopenharmony_ci 184362306a36Sopenharmony_ci for (;;) { 184462306a36Sopenharmony_ci id = atomic_long_read(&rb->desc_ring.tail_id); /* LMM(prb_first_seq:A) */ 184562306a36Sopenharmony_ci 184662306a36Sopenharmony_ci d_state = desc_read(desc_ring, id, &desc, &seq, NULL); /* LMM(prb_first_seq:B) */ 184762306a36Sopenharmony_ci 184862306a36Sopenharmony_ci /* 184962306a36Sopenharmony_ci * This loop will not be infinite because the tail is 185062306a36Sopenharmony_ci * _always_ in the finalized or reusable state. 185162306a36Sopenharmony_ci */ 185262306a36Sopenharmony_ci if (d_state == desc_finalized || d_state == desc_reusable) 185362306a36Sopenharmony_ci break; 185462306a36Sopenharmony_ci 185562306a36Sopenharmony_ci /* 185662306a36Sopenharmony_ci * Guarantee the last state load from desc_read() is before 185762306a36Sopenharmony_ci * reloading @tail_id in order to see a new tail in the case 185862306a36Sopenharmony_ci * that the descriptor has been recycled. This pairs with 185962306a36Sopenharmony_ci * desc_reserve:D. 186062306a36Sopenharmony_ci * 186162306a36Sopenharmony_ci * Memory barrier involvement: 186262306a36Sopenharmony_ci * 186362306a36Sopenharmony_ci * If prb_first_seq:B reads from desc_reserve:F, then 186462306a36Sopenharmony_ci * prb_first_seq:A reads from desc_push_tail:B. 186562306a36Sopenharmony_ci * 186662306a36Sopenharmony_ci * Relies on: 186762306a36Sopenharmony_ci * 186862306a36Sopenharmony_ci * MB from desc_push_tail:B to desc_reserve:F 186962306a36Sopenharmony_ci * matching 187062306a36Sopenharmony_ci * RMB prb_first_seq:B to prb_first_seq:A 187162306a36Sopenharmony_ci */ 187262306a36Sopenharmony_ci smp_rmb(); /* LMM(prb_first_seq:C) */ 187362306a36Sopenharmony_ci } 187462306a36Sopenharmony_ci 187562306a36Sopenharmony_ci return seq; 187662306a36Sopenharmony_ci} 187762306a36Sopenharmony_ci 187862306a36Sopenharmony_ci/* 187962306a36Sopenharmony_ci * Non-blocking read of a record. Updates @seq to the last finalized record 188062306a36Sopenharmony_ci * (which may have no data available). 188162306a36Sopenharmony_ci * 188262306a36Sopenharmony_ci * See the description of prb_read_valid() and prb_read_valid_info() 188362306a36Sopenharmony_ci * for details. 188462306a36Sopenharmony_ci */ 188562306a36Sopenharmony_cistatic bool _prb_read_valid(struct printk_ringbuffer *rb, u64 *seq, 188662306a36Sopenharmony_ci struct printk_record *r, unsigned int *line_count) 188762306a36Sopenharmony_ci{ 188862306a36Sopenharmony_ci u64 tail_seq; 188962306a36Sopenharmony_ci int err; 189062306a36Sopenharmony_ci 189162306a36Sopenharmony_ci while ((err = prb_read(rb, *seq, r, line_count))) { 189262306a36Sopenharmony_ci tail_seq = prb_first_seq(rb); 189362306a36Sopenharmony_ci 189462306a36Sopenharmony_ci if (*seq < tail_seq) { 189562306a36Sopenharmony_ci /* 189662306a36Sopenharmony_ci * Behind the tail. Catch up and try again. This 189762306a36Sopenharmony_ci * can happen for -ENOENT and -EINVAL cases. 189862306a36Sopenharmony_ci */ 189962306a36Sopenharmony_ci *seq = tail_seq; 190062306a36Sopenharmony_ci 190162306a36Sopenharmony_ci } else if (err == -ENOENT) { 190262306a36Sopenharmony_ci /* Record exists, but no data available. Skip. */ 190362306a36Sopenharmony_ci (*seq)++; 190462306a36Sopenharmony_ci 190562306a36Sopenharmony_ci } else { 190662306a36Sopenharmony_ci /* Non-existent/non-finalized record. Must stop. */ 190762306a36Sopenharmony_ci return false; 190862306a36Sopenharmony_ci } 190962306a36Sopenharmony_ci } 191062306a36Sopenharmony_ci 191162306a36Sopenharmony_ci return true; 191262306a36Sopenharmony_ci} 191362306a36Sopenharmony_ci 191462306a36Sopenharmony_ci/** 191562306a36Sopenharmony_ci * prb_read_valid() - Non-blocking read of a requested record or (if gone) 191662306a36Sopenharmony_ci * the next available record. 191762306a36Sopenharmony_ci * 191862306a36Sopenharmony_ci * @rb: The ringbuffer to read from. 191962306a36Sopenharmony_ci * @seq: The sequence number of the record to read. 192062306a36Sopenharmony_ci * @r: A record data buffer to store the read record to. 192162306a36Sopenharmony_ci * 192262306a36Sopenharmony_ci * This is the public function available to readers to read a record. 192362306a36Sopenharmony_ci * 192462306a36Sopenharmony_ci * The reader provides the @info and @text_buf buffers of @r to be 192562306a36Sopenharmony_ci * filled in. Any of the buffer pointers can be set to NULL if the reader 192662306a36Sopenharmony_ci * is not interested in that data. To ensure proper initialization of @r, 192762306a36Sopenharmony_ci * prb_rec_init_rd() should be used. 192862306a36Sopenharmony_ci * 192962306a36Sopenharmony_ci * Context: Any context. 193062306a36Sopenharmony_ci * Return: true if a record was read, otherwise false. 193162306a36Sopenharmony_ci * 193262306a36Sopenharmony_ci * On success, the reader must check r->info.seq to see which record was 193362306a36Sopenharmony_ci * actually read. This allows the reader to detect dropped records. 193462306a36Sopenharmony_ci * 193562306a36Sopenharmony_ci * Failure means @seq refers to a not yet written record. 193662306a36Sopenharmony_ci */ 193762306a36Sopenharmony_cibool prb_read_valid(struct printk_ringbuffer *rb, u64 seq, 193862306a36Sopenharmony_ci struct printk_record *r) 193962306a36Sopenharmony_ci{ 194062306a36Sopenharmony_ci return _prb_read_valid(rb, &seq, r, NULL); 194162306a36Sopenharmony_ci} 194262306a36Sopenharmony_ci 194362306a36Sopenharmony_ci/** 194462306a36Sopenharmony_ci * prb_read_valid_info() - Non-blocking read of meta data for a requested 194562306a36Sopenharmony_ci * record or (if gone) the next available record. 194662306a36Sopenharmony_ci * 194762306a36Sopenharmony_ci * @rb: The ringbuffer to read from. 194862306a36Sopenharmony_ci * @seq: The sequence number of the record to read. 194962306a36Sopenharmony_ci * @info: A buffer to store the read record meta data to. 195062306a36Sopenharmony_ci * @line_count: A buffer to store the number of lines in the record text. 195162306a36Sopenharmony_ci * 195262306a36Sopenharmony_ci * This is the public function available to readers to read only the 195362306a36Sopenharmony_ci * meta data of a record. 195462306a36Sopenharmony_ci * 195562306a36Sopenharmony_ci * The reader provides the @info, @line_count buffers to be filled in. 195662306a36Sopenharmony_ci * Either of the buffer pointers can be set to NULL if the reader is not 195762306a36Sopenharmony_ci * interested in that data. 195862306a36Sopenharmony_ci * 195962306a36Sopenharmony_ci * Context: Any context. 196062306a36Sopenharmony_ci * Return: true if a record's meta data was read, otherwise false. 196162306a36Sopenharmony_ci * 196262306a36Sopenharmony_ci * On success, the reader must check info->seq to see which record meta data 196362306a36Sopenharmony_ci * was actually read. This allows the reader to detect dropped records. 196462306a36Sopenharmony_ci * 196562306a36Sopenharmony_ci * Failure means @seq refers to a not yet written record. 196662306a36Sopenharmony_ci */ 196762306a36Sopenharmony_cibool prb_read_valid_info(struct printk_ringbuffer *rb, u64 seq, 196862306a36Sopenharmony_ci struct printk_info *info, unsigned int *line_count) 196962306a36Sopenharmony_ci{ 197062306a36Sopenharmony_ci struct printk_record r; 197162306a36Sopenharmony_ci 197262306a36Sopenharmony_ci prb_rec_init_rd(&r, info, NULL, 0); 197362306a36Sopenharmony_ci 197462306a36Sopenharmony_ci return _prb_read_valid(rb, &seq, &r, line_count); 197562306a36Sopenharmony_ci} 197662306a36Sopenharmony_ci 197762306a36Sopenharmony_ci/** 197862306a36Sopenharmony_ci * prb_first_valid_seq() - Get the sequence number of the oldest available 197962306a36Sopenharmony_ci * record. 198062306a36Sopenharmony_ci * 198162306a36Sopenharmony_ci * @rb: The ringbuffer to get the sequence number from. 198262306a36Sopenharmony_ci * 198362306a36Sopenharmony_ci * This is the public function available to readers to see what the 198462306a36Sopenharmony_ci * first/oldest valid sequence number is. 198562306a36Sopenharmony_ci * 198662306a36Sopenharmony_ci * This provides readers a starting point to begin iterating the ringbuffer. 198762306a36Sopenharmony_ci * 198862306a36Sopenharmony_ci * Context: Any context. 198962306a36Sopenharmony_ci * Return: The sequence number of the first/oldest record or, if the 199062306a36Sopenharmony_ci * ringbuffer is empty, 0 is returned. 199162306a36Sopenharmony_ci */ 199262306a36Sopenharmony_ciu64 prb_first_valid_seq(struct printk_ringbuffer *rb) 199362306a36Sopenharmony_ci{ 199462306a36Sopenharmony_ci u64 seq = 0; 199562306a36Sopenharmony_ci 199662306a36Sopenharmony_ci if (!_prb_read_valid(rb, &seq, NULL, NULL)) 199762306a36Sopenharmony_ci return 0; 199862306a36Sopenharmony_ci 199962306a36Sopenharmony_ci return seq; 200062306a36Sopenharmony_ci} 200162306a36Sopenharmony_ci 200262306a36Sopenharmony_ci/** 200362306a36Sopenharmony_ci * prb_next_seq() - Get the sequence number after the last available record. 200462306a36Sopenharmony_ci * 200562306a36Sopenharmony_ci * @rb: The ringbuffer to get the sequence number from. 200662306a36Sopenharmony_ci * 200762306a36Sopenharmony_ci * This is the public function available to readers to see what the next 200862306a36Sopenharmony_ci * newest sequence number available to readers will be. 200962306a36Sopenharmony_ci * 201062306a36Sopenharmony_ci * This provides readers a sequence number to jump to if all currently 201162306a36Sopenharmony_ci * available records should be skipped. 201262306a36Sopenharmony_ci * 201362306a36Sopenharmony_ci * Context: Any context. 201462306a36Sopenharmony_ci * Return: The sequence number of the next newest (not yet available) record 201562306a36Sopenharmony_ci * for readers. 201662306a36Sopenharmony_ci */ 201762306a36Sopenharmony_ciu64 prb_next_seq(struct printk_ringbuffer *rb) 201862306a36Sopenharmony_ci{ 201962306a36Sopenharmony_ci struct prb_desc_ring *desc_ring = &rb->desc_ring; 202062306a36Sopenharmony_ci enum desc_state d_state; 202162306a36Sopenharmony_ci unsigned long id; 202262306a36Sopenharmony_ci u64 seq; 202362306a36Sopenharmony_ci 202462306a36Sopenharmony_ci /* Check if the cached @id still points to a valid @seq. */ 202562306a36Sopenharmony_ci id = atomic_long_read(&desc_ring->last_finalized_id); 202662306a36Sopenharmony_ci d_state = desc_read(desc_ring, id, NULL, &seq, NULL); 202762306a36Sopenharmony_ci 202862306a36Sopenharmony_ci if (d_state == desc_finalized || d_state == desc_reusable) { 202962306a36Sopenharmony_ci /* 203062306a36Sopenharmony_ci * Begin searching after the last finalized record. 203162306a36Sopenharmony_ci * 203262306a36Sopenharmony_ci * On 0, the search must begin at 0 because of hack#2 203362306a36Sopenharmony_ci * of the bootstrapping phase it is not known if a 203462306a36Sopenharmony_ci * record at index 0 exists. 203562306a36Sopenharmony_ci */ 203662306a36Sopenharmony_ci if (seq != 0) 203762306a36Sopenharmony_ci seq++; 203862306a36Sopenharmony_ci } else { 203962306a36Sopenharmony_ci /* 204062306a36Sopenharmony_ci * The information about the last finalized sequence number 204162306a36Sopenharmony_ci * has gone. It should happen only when there is a flood of 204262306a36Sopenharmony_ci * new messages and the ringbuffer is rapidly recycled. 204362306a36Sopenharmony_ci * Give up and start from the beginning. 204462306a36Sopenharmony_ci */ 204562306a36Sopenharmony_ci seq = 0; 204662306a36Sopenharmony_ci } 204762306a36Sopenharmony_ci 204862306a36Sopenharmony_ci /* 204962306a36Sopenharmony_ci * The information about the last finalized @seq might be inaccurate. 205062306a36Sopenharmony_ci * Search forward to find the current one. 205162306a36Sopenharmony_ci */ 205262306a36Sopenharmony_ci while (_prb_read_valid(rb, &seq, NULL, NULL)) 205362306a36Sopenharmony_ci seq++; 205462306a36Sopenharmony_ci 205562306a36Sopenharmony_ci return seq; 205662306a36Sopenharmony_ci} 205762306a36Sopenharmony_ci 205862306a36Sopenharmony_ci/** 205962306a36Sopenharmony_ci * prb_init() - Initialize a ringbuffer to use provided external buffers. 206062306a36Sopenharmony_ci * 206162306a36Sopenharmony_ci * @rb: The ringbuffer to initialize. 206262306a36Sopenharmony_ci * @text_buf: The data buffer for text data. 206362306a36Sopenharmony_ci * @textbits: The size of @text_buf as a power-of-2 value. 206462306a36Sopenharmony_ci * @descs: The descriptor buffer for ringbuffer records. 206562306a36Sopenharmony_ci * @descbits: The count of @descs items as a power-of-2 value. 206662306a36Sopenharmony_ci * @infos: The printk_info buffer for ringbuffer records. 206762306a36Sopenharmony_ci * 206862306a36Sopenharmony_ci * This is the public function available to writers to setup a ringbuffer 206962306a36Sopenharmony_ci * during runtime using provided buffers. 207062306a36Sopenharmony_ci * 207162306a36Sopenharmony_ci * This must match the initialization of DEFINE_PRINTKRB(). 207262306a36Sopenharmony_ci * 207362306a36Sopenharmony_ci * Context: Any context. 207462306a36Sopenharmony_ci */ 207562306a36Sopenharmony_civoid prb_init(struct printk_ringbuffer *rb, 207662306a36Sopenharmony_ci char *text_buf, unsigned int textbits, 207762306a36Sopenharmony_ci struct prb_desc *descs, unsigned int descbits, 207862306a36Sopenharmony_ci struct printk_info *infos) 207962306a36Sopenharmony_ci{ 208062306a36Sopenharmony_ci memset(descs, 0, _DESCS_COUNT(descbits) * sizeof(descs[0])); 208162306a36Sopenharmony_ci memset(infos, 0, _DESCS_COUNT(descbits) * sizeof(infos[0])); 208262306a36Sopenharmony_ci 208362306a36Sopenharmony_ci rb->desc_ring.count_bits = descbits; 208462306a36Sopenharmony_ci rb->desc_ring.descs = descs; 208562306a36Sopenharmony_ci rb->desc_ring.infos = infos; 208662306a36Sopenharmony_ci atomic_long_set(&rb->desc_ring.head_id, DESC0_ID(descbits)); 208762306a36Sopenharmony_ci atomic_long_set(&rb->desc_ring.tail_id, DESC0_ID(descbits)); 208862306a36Sopenharmony_ci atomic_long_set(&rb->desc_ring.last_finalized_id, DESC0_ID(descbits)); 208962306a36Sopenharmony_ci 209062306a36Sopenharmony_ci rb->text_data_ring.size_bits = textbits; 209162306a36Sopenharmony_ci rb->text_data_ring.data = text_buf; 209262306a36Sopenharmony_ci atomic_long_set(&rb->text_data_ring.head_lpos, BLK0_LPOS(textbits)); 209362306a36Sopenharmony_ci atomic_long_set(&rb->text_data_ring.tail_lpos, BLK0_LPOS(textbits)); 209462306a36Sopenharmony_ci 209562306a36Sopenharmony_ci atomic_long_set(&rb->fail, 0); 209662306a36Sopenharmony_ci 209762306a36Sopenharmony_ci atomic_long_set(&(descs[_DESCS_COUNT(descbits) - 1].state_var), DESC0_SV(descbits)); 209862306a36Sopenharmony_ci descs[_DESCS_COUNT(descbits) - 1].text_blk_lpos.begin = FAILED_LPOS; 209962306a36Sopenharmony_ci descs[_DESCS_COUNT(descbits) - 1].text_blk_lpos.next = FAILED_LPOS; 210062306a36Sopenharmony_ci 210162306a36Sopenharmony_ci infos[0].seq = -(u64)_DESCS_COUNT(descbits); 210262306a36Sopenharmony_ci infos[_DESCS_COUNT(descbits) - 1].seq = 0; 210362306a36Sopenharmony_ci} 210462306a36Sopenharmony_ci 210562306a36Sopenharmony_ci/** 210662306a36Sopenharmony_ci * prb_record_text_space() - Query the full actual used ringbuffer space for 210762306a36Sopenharmony_ci * the text data of a reserved entry. 210862306a36Sopenharmony_ci * 210962306a36Sopenharmony_ci * @e: The successfully reserved entry to query. 211062306a36Sopenharmony_ci * 211162306a36Sopenharmony_ci * This is the public function available to writers to see how much actual 211262306a36Sopenharmony_ci * space is used in the ringbuffer to store the text data of the specified 211362306a36Sopenharmony_ci * entry. 211462306a36Sopenharmony_ci * 211562306a36Sopenharmony_ci * This function is only valid if @e has been successfully reserved using 211662306a36Sopenharmony_ci * prb_reserve(). 211762306a36Sopenharmony_ci * 211862306a36Sopenharmony_ci * Context: Any context. 211962306a36Sopenharmony_ci * Return: The size in bytes used by the text data of the associated record. 212062306a36Sopenharmony_ci */ 212162306a36Sopenharmony_ciunsigned int prb_record_text_space(struct prb_reserved_entry *e) 212262306a36Sopenharmony_ci{ 212362306a36Sopenharmony_ci return e->text_space; 212462306a36Sopenharmony_ci} 2125