@@ -71,6 +71,20 @@ static int find_dvsec_afu_ctrl(struct pci_dev *dev, u8 afu_idx)
7171 return 0 ;
7272}
7373
74+ /**
75+ * get_function_0() - Find a related PCI device (function 0)
76+ * @device: PCI device to match
77+ *
78+ * Returns a pointer to the related device, or null if not found
79+ */
80+ static struct pci_dev * get_function_0 (struct pci_dev * dev )
81+ {
82+ unsigned int devfn = PCI_DEVFN (PCI_SLOT (dev -> devfn ), 0 );
83+
84+ return pci_get_domain_bus_and_slot (pci_domain_nr (dev -> bus ),
85+ dev -> bus -> number , devfn );
86+ }
87+
7488static void read_pasid (struct pci_dev * dev , struct ocxl_fn_config * fn )
7589{
7690 u16 val ;
@@ -159,14 +173,15 @@ static int read_dvsec_afu_info(struct pci_dev *dev, struct ocxl_fn_config *fn)
159173static int read_dvsec_vendor (struct pci_dev * dev )
160174{
161175 int pos ;
162- u32 cfg , tlx , dlx ;
176+ u32 cfg , tlx , dlx , reset_reload ;
163177
164178 /*
165- * vendor specific DVSEC is optional
179+ * vendor specific DVSEC, for IBM images only. Some older
180+ * images may not have it
166181 *
167- * It's currently only used on function 0 to specify the
168- * version of some logic blocks. Some older images may not
169- * even have it so we ignore any errors
182+ * It's only used on function 0 to specify the version of some
183+ * logic blocks and to give access to special registers to
184+ * enable host-based flashing.
170185 */
171186 if (PCI_FUNC (dev -> devfn ) != 0 )
172187 return 0 ;
@@ -178,11 +193,67 @@ static int read_dvsec_vendor(struct pci_dev *dev)
178193 pci_read_config_dword (dev , pos + OCXL_DVSEC_VENDOR_CFG_VERS , & cfg );
179194 pci_read_config_dword (dev , pos + OCXL_DVSEC_VENDOR_TLX_VERS , & tlx );
180195 pci_read_config_dword (dev , pos + OCXL_DVSEC_VENDOR_DLX_VERS , & dlx );
196+ pci_read_config_dword (dev , pos + OCXL_DVSEC_VENDOR_RESET_RELOAD ,
197+ & reset_reload );
181198
182199 dev_dbg (& dev -> dev , "Vendor specific DVSEC:\n" );
183200 dev_dbg (& dev -> dev , " CFG version = 0x%x\n" , cfg );
184201 dev_dbg (& dev -> dev , " TLX version = 0x%x\n" , tlx );
185202 dev_dbg (& dev -> dev , " DLX version = 0x%x\n" , dlx );
203+ dev_dbg (& dev -> dev , " ResetReload = 0x%x\n" , reset_reload );
204+ return 0 ;
205+ }
206+
207+ static int get_dvsec_vendor0 (struct pci_dev * dev , struct pci_dev * * dev0 ,
208+ int * out_pos )
209+ {
210+ int pos ;
211+
212+ if (PCI_FUNC (dev -> devfn ) != 0 ) {
213+ dev = get_function_0 (dev );
214+ if (!dev )
215+ return -1 ;
216+ }
217+ pos = find_dvsec (dev , OCXL_DVSEC_VENDOR_ID );
218+ if (!pos )
219+ return -1 ;
220+ * dev0 = dev ;
221+ * out_pos = pos ;
222+ return 0 ;
223+ }
224+
225+ int ocxl_config_get_reset_reload (struct pci_dev * dev , int * val )
226+ {
227+ struct pci_dev * dev0 ;
228+ u32 reset_reload ;
229+ int pos ;
230+
231+ if (get_dvsec_vendor0 (dev , & dev0 , & pos ))
232+ return -1 ;
233+
234+ pci_read_config_dword (dev0 , pos + OCXL_DVSEC_VENDOR_RESET_RELOAD ,
235+ & reset_reload );
236+ * val = !!(reset_reload & BIT (0 ));
237+ return 0 ;
238+ }
239+
240+ int ocxl_config_set_reset_reload (struct pci_dev * dev , int val )
241+ {
242+ struct pci_dev * dev0 ;
243+ u32 reset_reload ;
244+ int pos ;
245+
246+ if (get_dvsec_vendor0 (dev , & dev0 , & pos ))
247+ return -1 ;
248+
249+ pci_read_config_dword (dev0 , pos + OCXL_DVSEC_VENDOR_RESET_RELOAD ,
250+ & reset_reload );
251+ if (val )
252+ reset_reload |= BIT (0 );
253+ else
254+ reset_reload &= ~BIT (0 );
255+ pci_write_config_dword (dev0 , pos + OCXL_DVSEC_VENDOR_RESET_RELOAD ,
256+ reset_reload );
186257 return 0 ;
187258}
188259
0 commit comments