xref: /aosp_15_r20/external/pciutils/lmr/lmr.h (revision c2e0c6b56a71da9abe8df5c8348fb3eb5c2c9251)
1*c2e0c6b5SAndroid Build Coastguard Worker /*
2*c2e0c6b5SAndroid Build Coastguard Worker  *	The PCI Utilities -- Margining utility main header
3*c2e0c6b5SAndroid Build Coastguard Worker  *
4*c2e0c6b5SAndroid Build Coastguard Worker  *	Copyright (c) 2023-2024 KNS Group LLC (YADRO)
5*c2e0c6b5SAndroid Build Coastguard Worker  *
6*c2e0c6b5SAndroid Build Coastguard Worker  *	Can be freely distributed and used under the terms of the GNU GPL v2+.
7*c2e0c6b5SAndroid Build Coastguard Worker  *
8*c2e0c6b5SAndroid Build Coastguard Worker  *	SPDX-License-Identifier: GPL-2.0-or-later
9*c2e0c6b5SAndroid Build Coastguard Worker  */
10*c2e0c6b5SAndroid Build Coastguard Worker 
11*c2e0c6b5SAndroid Build Coastguard Worker #ifndef _LMR_H
12*c2e0c6b5SAndroid Build Coastguard Worker #define _LMR_H
13*c2e0c6b5SAndroid Build Coastguard Worker 
14*c2e0c6b5SAndroid Build Coastguard Worker #include <stdbool.h>
15*c2e0c6b5SAndroid Build Coastguard Worker 
16*c2e0c6b5SAndroid Build Coastguard Worker #include "pciutils.h"
17*c2e0c6b5SAndroid Build Coastguard Worker 
18*c2e0c6b5SAndroid Build Coastguard Worker enum margin_hw { MARGIN_HW_DEFAULT, MARGIN_ICE_LAKE_RC };
19*c2e0c6b5SAndroid Build Coastguard Worker 
20*c2e0c6b5SAndroid Build Coastguard Worker // in ps
21*c2e0c6b5SAndroid Build Coastguard Worker static const double margin_ui[] = { 62.5, 31.25 };
22*c2e0c6b5SAndroid Build Coastguard Worker 
23*c2e0c6b5SAndroid Build Coastguard Worker /* PCI Device wrapper for margining functions */
24*c2e0c6b5SAndroid Build Coastguard Worker struct margin_dev {
25*c2e0c6b5SAndroid Build Coastguard Worker   struct pci_dev *dev;
26*c2e0c6b5SAndroid Build Coastguard Worker   int lmr_cap_addr;
27*c2e0c6b5SAndroid Build Coastguard Worker   u8 neg_width;
28*c2e0c6b5SAndroid Build Coastguard Worker   u8 max_width;
29*c2e0c6b5SAndroid Build Coastguard Worker   u8 retimers_n;
30*c2e0c6b5SAndroid Build Coastguard Worker   u8 link_speed;
31*c2e0c6b5SAndroid Build Coastguard Worker 
32*c2e0c6b5SAndroid Build Coastguard Worker   enum margin_hw hw;
33*c2e0c6b5SAndroid Build Coastguard Worker 
34*c2e0c6b5SAndroid Build Coastguard Worker   /* Saved Device settings to restore after margining */
35*c2e0c6b5SAndroid Build Coastguard Worker   u8 aspm;
36*c2e0c6b5SAndroid Build Coastguard Worker   bool hasd; // Hardware Autonomous Speed Disable
37*c2e0c6b5SAndroid Build Coastguard Worker   bool hawd; // Hardware Autonomous Width Disable
38*c2e0c6b5SAndroid Build Coastguard Worker };
39*c2e0c6b5SAndroid Build Coastguard Worker 
40*c2e0c6b5SAndroid Build Coastguard Worker /* Specification Revision 5.0 Table 8-11 */
41*c2e0c6b5SAndroid Build Coastguard Worker struct margin_params {
42*c2e0c6b5SAndroid Build Coastguard Worker   bool ind_error_sampler;
43*c2e0c6b5SAndroid Build Coastguard Worker   bool sample_report_method;
44*c2e0c6b5SAndroid Build Coastguard Worker   bool ind_left_right_tim;
45*c2e0c6b5SAndroid Build Coastguard Worker   bool ind_up_down_volt;
46*c2e0c6b5SAndroid Build Coastguard Worker   bool volt_support;
47*c2e0c6b5SAndroid Build Coastguard Worker 
48*c2e0c6b5SAndroid Build Coastguard Worker   u8 max_lanes;
49*c2e0c6b5SAndroid Build Coastguard Worker 
50*c2e0c6b5SAndroid Build Coastguard Worker   u8 timing_steps;
51*c2e0c6b5SAndroid Build Coastguard Worker   u8 timing_offset;
52*c2e0c6b5SAndroid Build Coastguard Worker 
53*c2e0c6b5SAndroid Build Coastguard Worker   u8 volt_steps;
54*c2e0c6b5SAndroid Build Coastguard Worker   u8 volt_offset;
55*c2e0c6b5SAndroid Build Coastguard Worker 
56*c2e0c6b5SAndroid Build Coastguard Worker   u8 sample_rate_v;
57*c2e0c6b5SAndroid Build Coastguard Worker   u8 sample_rate_t;
58*c2e0c6b5SAndroid Build Coastguard Worker };
59*c2e0c6b5SAndroid Build Coastguard Worker 
60*c2e0c6b5SAndroid Build Coastguard Worker /* Step Margin Execution Status - Step command response */
61*c2e0c6b5SAndroid Build Coastguard Worker enum margin_step_exec_sts {
62*c2e0c6b5SAndroid Build Coastguard Worker   MARGIN_NAK = 0, // NAK/Set up for margin
63*c2e0c6b5SAndroid Build Coastguard Worker   MARGIN_LIM,     // Too many errors (device limit)
64*c2e0c6b5SAndroid Build Coastguard Worker   MARGIN_THR      // Test threshold has been reached
65*c2e0c6b5SAndroid Build Coastguard Worker };
66*c2e0c6b5SAndroid Build Coastguard Worker 
67*c2e0c6b5SAndroid Build Coastguard Worker enum margin_dir { VOLT_UP = 0, VOLT_DOWN, TIM_LEFT, TIM_RIGHT };
68*c2e0c6b5SAndroid Build Coastguard Worker 
69*c2e0c6b5SAndroid Build Coastguard Worker /* Margining results of one lane of the receiver */
70*c2e0c6b5SAndroid Build Coastguard Worker struct margin_res_lane {
71*c2e0c6b5SAndroid Build Coastguard Worker   u8 lane;
72*c2e0c6b5SAndroid Build Coastguard Worker   u8 steps[4];
73*c2e0c6b5SAndroid Build Coastguard Worker   enum margin_step_exec_sts statuses[4];
74*c2e0c6b5SAndroid Build Coastguard Worker };
75*c2e0c6b5SAndroid Build Coastguard Worker 
76*c2e0c6b5SAndroid Build Coastguard Worker /* Reason not to run margining test on the Link/Receiver */
77*c2e0c6b5SAndroid Build Coastguard Worker enum margin_test_status {
78*c2e0c6b5SAndroid Build Coastguard Worker   MARGIN_TEST_OK = 0,
79*c2e0c6b5SAndroid Build Coastguard Worker   MARGIN_TEST_READY_BIT,
80*c2e0c6b5SAndroid Build Coastguard Worker   MARGIN_TEST_CAPS,
81*c2e0c6b5SAndroid Build Coastguard Worker 
82*c2e0c6b5SAndroid Build Coastguard Worker   // Couldn't run test
83*c2e0c6b5SAndroid Build Coastguard Worker   MARGIN_TEST_PREREQS,
84*c2e0c6b5SAndroid Build Coastguard Worker   MARGIN_TEST_ARGS_LANES,
85*c2e0c6b5SAndroid Build Coastguard Worker   MARGIN_TEST_ARGS_RECVS,
86*c2e0c6b5SAndroid Build Coastguard Worker   MARGIN_TEST_ASPM
87*c2e0c6b5SAndroid Build Coastguard Worker };
88*c2e0c6b5SAndroid Build Coastguard Worker 
89*c2e0c6b5SAndroid Build Coastguard Worker /* All lanes Receiver results */
90*c2e0c6b5SAndroid Build Coastguard Worker struct margin_results {
91*c2e0c6b5SAndroid Build Coastguard Worker   u8 recvn; // Receiver Number; from 1 to 6
92*c2e0c6b5SAndroid Build Coastguard Worker   struct margin_params params;
93*c2e0c6b5SAndroid Build Coastguard Worker   bool lane_reversal;
94*c2e0c6b5SAndroid Build Coastguard Worker   u8 link_speed;
95*c2e0c6b5SAndroid Build Coastguard Worker 
96*c2e0c6b5SAndroid Build Coastguard Worker   enum margin_test_status test_status;
97*c2e0c6b5SAndroid Build Coastguard Worker 
98*c2e0c6b5SAndroid Build Coastguard Worker   /* Used to convert steps to physical quantity.
99*c2e0c6b5SAndroid Build Coastguard Worker      Calculated from MaxOffset and NumSteps     */
100*c2e0c6b5SAndroid Build Coastguard Worker   double tim_coef; // from steps to % UI
101*c2e0c6b5SAndroid Build Coastguard Worker   double volt_coef;
102*c2e0c6b5SAndroid Build Coastguard Worker 
103*c2e0c6b5SAndroid Build Coastguard Worker   bool tim_off_reported;
104*c2e0c6b5SAndroid Build Coastguard Worker   bool volt_off_reported;
105*c2e0c6b5SAndroid Build Coastguard Worker 
106*c2e0c6b5SAndroid Build Coastguard Worker   u8 lanes_n;
107*c2e0c6b5SAndroid Build Coastguard Worker   struct margin_res_lane *lanes;
108*c2e0c6b5SAndroid Build Coastguard Worker };
109*c2e0c6b5SAndroid Build Coastguard Worker 
110*c2e0c6b5SAndroid Build Coastguard Worker /* pcilmr arguments */
111*c2e0c6b5SAndroid Build Coastguard Worker 
112*c2e0c6b5SAndroid Build Coastguard Worker // Common args
113*c2e0c6b5SAndroid Build Coastguard Worker struct margin_com_args {
114*c2e0c6b5SAndroid Build Coastguard Worker   u8 error_limit;    // [0; 63]
115*c2e0c6b5SAndroid Build Coastguard Worker   bool run_margin;   // Or print params only
116*c2e0c6b5SAndroid Build Coastguard Worker   u8 verbosity;      // 0 - basic;
117*c2e0c6b5SAndroid Build Coastguard Worker                      // 1 - add info about remaining time and lanes in progress during margining
118*c2e0c6b5SAndroid Build Coastguard Worker   u64 steps_utility; // For ETA logging
119*c2e0c6b5SAndroid Build Coastguard Worker   bool save_csv;
120*c2e0c6b5SAndroid Build Coastguard Worker   char *dir_for_csv;
121*c2e0c6b5SAndroid Build Coastguard Worker   u8 dwell_time;
122*c2e0c6b5SAndroid Build Coastguard Worker };
123*c2e0c6b5SAndroid Build Coastguard Worker 
124*c2e0c6b5SAndroid Build Coastguard Worker struct margin_recv_args {
125*c2e0c6b5SAndroid Build Coastguard Worker   // Grading options
126*c2e0c6b5SAndroid Build Coastguard Worker   struct {
127*c2e0c6b5SAndroid Build Coastguard Worker     bool valid;
128*c2e0c6b5SAndroid Build Coastguard Worker     double criteria; // in ps/mV
129*c2e0c6b5SAndroid Build Coastguard Worker     bool one_side_is_whole;
130*c2e0c6b5SAndroid Build Coastguard Worker   } t, v;
131*c2e0c6b5SAndroid Build Coastguard Worker };
132*c2e0c6b5SAndroid Build Coastguard Worker 
133*c2e0c6b5SAndroid Build Coastguard Worker struct margin_link_args {
134*c2e0c6b5SAndroid Build Coastguard Worker   struct margin_com_args *common;
135*c2e0c6b5SAndroid Build Coastguard Worker   u8 steps_t;        // 0 == use NumTimingSteps
136*c2e0c6b5SAndroid Build Coastguard Worker   u8 steps_v;        // 0 == use NumVoltageSteps
137*c2e0c6b5SAndroid Build Coastguard Worker   u8 parallel_lanes; // [1; MaxLanes + 1]
138*c2e0c6b5SAndroid Build Coastguard Worker   u8 recvs[6];       // Receivers Numbers
139*c2e0c6b5SAndroid Build Coastguard Worker   u8 recvs_n;        // 0 == margin all available receivers
140*c2e0c6b5SAndroid Build Coastguard Worker   struct margin_recv_args recv_args[6];
141*c2e0c6b5SAndroid Build Coastguard Worker   u8 lanes[32]; // Lanes to Margin
142*c2e0c6b5SAndroid Build Coastguard Worker   u8 lanes_n;   // 0 == margin all available lanes
143*c2e0c6b5SAndroid Build Coastguard Worker };
144*c2e0c6b5SAndroid Build Coastguard Worker 
145*c2e0c6b5SAndroid Build Coastguard Worker struct margin_link {
146*c2e0c6b5SAndroid Build Coastguard Worker   struct margin_dev down_port;
147*c2e0c6b5SAndroid Build Coastguard Worker   struct margin_dev up_port;
148*c2e0c6b5SAndroid Build Coastguard Worker   struct margin_link_args args;
149*c2e0c6b5SAndroid Build Coastguard Worker };
150*c2e0c6b5SAndroid Build Coastguard Worker 
151*c2e0c6b5SAndroid Build Coastguard Worker /* Receiver structure */
152*c2e0c6b5SAndroid Build Coastguard Worker struct margin_recv {
153*c2e0c6b5SAndroid Build Coastguard Worker   struct margin_dev *dev;
154*c2e0c6b5SAndroid Build Coastguard Worker   u8 recvn; // Receiver Number; from 1 to 6
155*c2e0c6b5SAndroid Build Coastguard Worker   bool lane_reversal;
156*c2e0c6b5SAndroid Build Coastguard Worker   struct margin_params *params;
157*c2e0c6b5SAndroid Build Coastguard Worker 
158*c2e0c6b5SAndroid Build Coastguard Worker   u8 parallel_lanes;
159*c2e0c6b5SAndroid Build Coastguard Worker   u8 error_limit;
160*c2e0c6b5SAndroid Build Coastguard Worker   u8 dwell_time;
161*c2e0c6b5SAndroid Build Coastguard Worker };
162*c2e0c6b5SAndroid Build Coastguard Worker 
163*c2e0c6b5SAndroid Build Coastguard Worker struct margin_lanes_data {
164*c2e0c6b5SAndroid Build Coastguard Worker   struct margin_recv *recv;
165*c2e0c6b5SAndroid Build Coastguard Worker 
166*c2e0c6b5SAndroid Build Coastguard Worker   struct margin_res_lane *results;
167*c2e0c6b5SAndroid Build Coastguard Worker   u8 *lanes_numbers;
168*c2e0c6b5SAndroid Build Coastguard Worker   u8 lanes_n;
169*c2e0c6b5SAndroid Build Coastguard Worker 
170*c2e0c6b5SAndroid Build Coastguard Worker   bool ind;
171*c2e0c6b5SAndroid Build Coastguard Worker   enum margin_dir dir;
172*c2e0c6b5SAndroid Build Coastguard Worker 
173*c2e0c6b5SAndroid Build Coastguard Worker   u8 steps_lane_done;
174*c2e0c6b5SAndroid Build Coastguard Worker   u8 steps_lane_total;
175*c2e0c6b5SAndroid Build Coastguard Worker   u64 *steps_utility;
176*c2e0c6b5SAndroid Build Coastguard Worker 
177*c2e0c6b5SAndroid Build Coastguard Worker   u8 verbosity;
178*c2e0c6b5SAndroid Build Coastguard Worker };
179*c2e0c6b5SAndroid Build Coastguard Worker 
180*c2e0c6b5SAndroid Build Coastguard Worker /* margin_args */
181*c2e0c6b5SAndroid Build Coastguard Worker 
182*c2e0c6b5SAndroid Build Coastguard Worker enum margin_mode { MARGIN, FULL, SCAN };
183*c2e0c6b5SAndroid Build Coastguard Worker 
184*c2e0c6b5SAndroid Build Coastguard Worker extern const char *usage;
185*c2e0c6b5SAndroid Build Coastguard Worker 
186*c2e0c6b5SAndroid Build Coastguard Worker struct margin_link *margin_parse_util_args(struct pci_access *pacc, int argc, char **argv,
187*c2e0c6b5SAndroid Build Coastguard Worker                                            enum margin_mode mode, u8 *links_n);
188*c2e0c6b5SAndroid Build Coastguard Worker 
189*c2e0c6b5SAndroid Build Coastguard Worker /* margin_hw */
190*c2e0c6b5SAndroid Build Coastguard Worker 
191*c2e0c6b5SAndroid Build Coastguard Worker bool margin_port_is_down(struct pci_dev *dev);
192*c2e0c6b5SAndroid Build Coastguard Worker 
193*c2e0c6b5SAndroid Build Coastguard Worker /* Results through down/up ports */
194*c2e0c6b5SAndroid Build Coastguard Worker bool margin_find_pair(struct pci_access *pacc, struct pci_dev *dev, struct pci_dev **down_port,
195*c2e0c6b5SAndroid Build Coastguard Worker                       struct pci_dev **up_port);
196*c2e0c6b5SAndroid Build Coastguard Worker 
197*c2e0c6b5SAndroid Build Coastguard Worker /* Verify that devices form the link with 16 GT/s or 32 GT/s data rate */
198*c2e0c6b5SAndroid Build Coastguard Worker bool margin_verify_link(struct pci_dev *down_port, struct pci_dev *up_port);
199*c2e0c6b5SAndroid Build Coastguard Worker 
200*c2e0c6b5SAndroid Build Coastguard Worker /* Check Margining Ready bit from Margining Port Status Register */
201*c2e0c6b5SAndroid Build Coastguard Worker bool margin_check_ready_bit(struct pci_dev *dev);
202*c2e0c6b5SAndroid Build Coastguard Worker 
203*c2e0c6b5SAndroid Build Coastguard Worker /* Verify link and fill wrappers */
204*c2e0c6b5SAndroid Build Coastguard Worker bool margin_fill_link(struct pci_dev *down_port, struct pci_dev *up_port,
205*c2e0c6b5SAndroid Build Coastguard Worker                       struct margin_link *wrappers);
206*c2e0c6b5SAndroid Build Coastguard Worker 
207*c2e0c6b5SAndroid Build Coastguard Worker /* Disable ASPM, set Hardware Autonomous Speed/Width Disable bits */
208*c2e0c6b5SAndroid Build Coastguard Worker bool margin_prep_link(struct margin_link *link);
209*c2e0c6b5SAndroid Build Coastguard Worker 
210*c2e0c6b5SAndroid Build Coastguard Worker /* Restore ASPM, Hardware Autonomous Speed/Width settings */
211*c2e0c6b5SAndroid Build Coastguard Worker void margin_restore_link(struct margin_link *link);
212*c2e0c6b5SAndroid Build Coastguard Worker 
213*c2e0c6b5SAndroid Build Coastguard Worker /* margin */
214*c2e0c6b5SAndroid Build Coastguard Worker 
215*c2e0c6b5SAndroid Build Coastguard Worker /* Fill margin_params without calling other functions */
216*c2e0c6b5SAndroid Build Coastguard Worker bool margin_read_params(struct pci_access *pacc, struct pci_dev *dev, u8 recvn,
217*c2e0c6b5SAndroid Build Coastguard Worker                         struct margin_params *params);
218*c2e0c6b5SAndroid Build Coastguard Worker 
219*c2e0c6b5SAndroid Build Coastguard Worker enum margin_test_status margin_process_args(struct margin_link *link);
220*c2e0c6b5SAndroid Build Coastguard Worker 
221*c2e0c6b5SAndroid Build Coastguard Worker /* Awaits that links are prepared through process_args.
222*c2e0c6b5SAndroid Build Coastguard Worker    Returns number of margined Receivers through recvs_n */
223*c2e0c6b5SAndroid Build Coastguard Worker struct margin_results *margin_test_link(struct margin_link *link, u8 *recvs_n);
224*c2e0c6b5SAndroid Build Coastguard Worker 
225*c2e0c6b5SAndroid Build Coastguard Worker void margin_free_results(struct margin_results *results, u8 results_n);
226*c2e0c6b5SAndroid Build Coastguard Worker 
227*c2e0c6b5SAndroid Build Coastguard Worker /* margin_log */
228*c2e0c6b5SAndroid Build Coastguard Worker 
229*c2e0c6b5SAndroid Build Coastguard Worker extern bool margin_global_logging;
230*c2e0c6b5SAndroid Build Coastguard Worker extern bool margin_print_domain;
231*c2e0c6b5SAndroid Build Coastguard Worker 
232*c2e0c6b5SAndroid Build Coastguard Worker void margin_log(char *format, ...);
233*c2e0c6b5SAndroid Build Coastguard Worker 
234*c2e0c6b5SAndroid Build Coastguard Worker /* b:d.f -> b:d.f */
235*c2e0c6b5SAndroid Build Coastguard Worker void margin_log_bdfs(struct pci_dev *down_port, struct pci_dev *up_port);
236*c2e0c6b5SAndroid Build Coastguard Worker void margin_gen_bdfs(struct pci_dev *down_port, struct pci_dev *up_port, char *dest, size_t maxlen);
237*c2e0c6b5SAndroid Build Coastguard Worker 
238*c2e0c6b5SAndroid Build Coastguard Worker /* Print Link header (bdfs, neg_width, speed) */
239*c2e0c6b5SAndroid Build Coastguard Worker void margin_log_link(struct margin_link *link);
240*c2e0c6b5SAndroid Build Coastguard Worker 
241*c2e0c6b5SAndroid Build Coastguard Worker void margin_log_params(struct margin_params *params);
242*c2e0c6b5SAndroid Build Coastguard Worker 
243*c2e0c6b5SAndroid Build Coastguard Worker /* Print receiver number */
244*c2e0c6b5SAndroid Build Coastguard Worker void margin_log_recvn(struct margin_recv *recv);
245*c2e0c6b5SAndroid Build Coastguard Worker 
246*c2e0c6b5SAndroid Build Coastguard Worker /* Print full info from Receiver struct */
247*c2e0c6b5SAndroid Build Coastguard Worker void margin_log_receiver(struct margin_recv *recv);
248*c2e0c6b5SAndroid Build Coastguard Worker 
249*c2e0c6b5SAndroid Build Coastguard Worker /* Margining in progress log */
250*c2e0c6b5SAndroid Build Coastguard Worker void margin_log_margining(struct margin_lanes_data arg);
251*c2e0c6b5SAndroid Build Coastguard Worker 
252*c2e0c6b5SAndroid Build Coastguard Worker void margin_log_hw_quirks(struct margin_recv *recv);
253*c2e0c6b5SAndroid Build Coastguard Worker 
254*c2e0c6b5SAndroid Build Coastguard Worker /* margin_results */
255*c2e0c6b5SAndroid Build Coastguard Worker 
256*c2e0c6b5SAndroid Build Coastguard Worker // Min values are taken from PCIe Base Spec Rev. 5.0 Section 8.4.2.
257*c2e0c6b5SAndroid Build Coastguard Worker // Rec values are based on PCIe Arch PHY Test Spec Rev 5.0
258*c2e0c6b5SAndroid Build Coastguard Worker // (Transmitter Electrical Compliance)
259*c2e0c6b5SAndroid Build Coastguard Worker 
260*c2e0c6b5SAndroid Build Coastguard Worker // values in ps
261*c2e0c6b5SAndroid Build Coastguard Worker static const double margin_ew_min[] = { 18.75, 9.375 };
262*c2e0c6b5SAndroid Build Coastguard Worker static const double margin_ew_rec[] = { 23.75, 10.1565 };
263*c2e0c6b5SAndroid Build Coastguard Worker 
264*c2e0c6b5SAndroid Build Coastguard Worker static const double margin_eh_min[] = { 15, 15 };
265*c2e0c6b5SAndroid Build Coastguard Worker static const double margin_eh_rec[] = { 21, 19.75 };
266*c2e0c6b5SAndroid Build Coastguard Worker 
267*c2e0c6b5SAndroid Build Coastguard Worker void margin_results_print_brief(struct margin_results *results, u8 recvs_n,
268*c2e0c6b5SAndroid Build Coastguard Worker                                 struct margin_link_args *args);
269*c2e0c6b5SAndroid Build Coastguard Worker 
270*c2e0c6b5SAndroid Build Coastguard Worker void margin_results_save_csv(struct margin_results *results, u8 recvs_n, struct margin_link *link);
271*c2e0c6b5SAndroid Build Coastguard Worker 
272*c2e0c6b5SAndroid Build Coastguard Worker #endif
273