xref: /onnv-gate/usr/src/uts/sun4v/io/px/px_libhv.c (revision 11245:28613b254aad)
17596SAlan.Adamson@Sun.COM /*
27596SAlan.Adamson@Sun.COM  * CDDL HEADER START
37596SAlan.Adamson@Sun.COM  *
47596SAlan.Adamson@Sun.COM  * The contents of this file are subject to the terms of the
57596SAlan.Adamson@Sun.COM  * Common Development and Distribution License (the "License").
67596SAlan.Adamson@Sun.COM  * You may not use this file except in compliance with the License.
77596SAlan.Adamson@Sun.COM  *
87596SAlan.Adamson@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97596SAlan.Adamson@Sun.COM  * or http://www.opensolaris.org/os/licensing.
107596SAlan.Adamson@Sun.COM  * See the License for the specific language governing permissions
117596SAlan.Adamson@Sun.COM  * and limitations under the License.
127596SAlan.Adamson@Sun.COM  *
137596SAlan.Adamson@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
147596SAlan.Adamson@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157596SAlan.Adamson@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
167596SAlan.Adamson@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
177596SAlan.Adamson@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
187596SAlan.Adamson@Sun.COM  *
197596SAlan.Adamson@Sun.COM  * CDDL HEADER END
207596SAlan.Adamson@Sun.COM  */
217596SAlan.Adamson@Sun.COM /*
2210595SShesha.Sreenivasamurthy@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237596SAlan.Adamson@Sun.COM  * Use is subject to license terms.
247596SAlan.Adamson@Sun.COM  */
257596SAlan.Adamson@Sun.COM 
267596SAlan.Adamson@Sun.COM #include <sys/types.h>
277596SAlan.Adamson@Sun.COM #include <sys/sysmacros.h>
287596SAlan.Adamson@Sun.COM #include <sys/ddi.h>
297596SAlan.Adamson@Sun.COM #include <sys/async.h>
307596SAlan.Adamson@Sun.COM #include <sys/sunddi.h>
317596SAlan.Adamson@Sun.COM #include <sys/ddifm.h>
327596SAlan.Adamson@Sun.COM #include <sys/fm/protocol.h>
337596SAlan.Adamson@Sun.COM #include <sys/vmem.h>
347596SAlan.Adamson@Sun.COM #include <sys/intr.h>
357596SAlan.Adamson@Sun.COM #include <sys/ivintr.h>
367596SAlan.Adamson@Sun.COM #include <sys/errno.h>
377596SAlan.Adamson@Sun.COM #include <sys/hypervisor_api.h>
387596SAlan.Adamson@Sun.COM #include <sys/hsvc.h>
39*11245SZhijun.Fu@Sun.COM #include <sys/pci_cfgacc.h>
40*11245SZhijun.Fu@Sun.COM #include <sys/pci_cfgacc_4v.h>
417596SAlan.Adamson@Sun.COM #include <px_obj.h>
427596SAlan.Adamson@Sun.COM #include <sys/machsystm.h>
437596SAlan.Adamson@Sun.COM #include "px_lib4v.h"
447596SAlan.Adamson@Sun.COM 
457596SAlan.Adamson@Sun.COM #define	MPS_SET		0
467596SAlan.Adamson@Sun.COM #define	MPS_GET		1
477596SAlan.Adamson@Sun.COM 
487596SAlan.Adamson@Sun.COM static uint64_t hvio_rp_mps(devhandle_t dev_hdl, pci_device_t bdf, int32_t *mps,
497596SAlan.Adamson@Sun.COM 	int op);
507596SAlan.Adamson@Sun.COM 
517596SAlan.Adamson@Sun.COM uint64_t
hvio_get_rp_mps_cap(devhandle_t dev_hdl,pci_device_t bdf,int32_t * mps_cap)527596SAlan.Adamson@Sun.COM hvio_get_rp_mps_cap(devhandle_t dev_hdl, pci_device_t bdf, int32_t *mps_cap)
537596SAlan.Adamson@Sun.COM {
547596SAlan.Adamson@Sun.COM 	return (hvio_rp_mps(dev_hdl, bdf, mps_cap, MPS_GET));
557596SAlan.Adamson@Sun.COM }
567596SAlan.Adamson@Sun.COM 
577596SAlan.Adamson@Sun.COM uint64_t
hvio_set_rp_mps(devhandle_t dev_hdl,pci_device_t bdf,int32_t mps)587596SAlan.Adamson@Sun.COM hvio_set_rp_mps(devhandle_t dev_hdl, pci_device_t bdf, int32_t mps)
597596SAlan.Adamson@Sun.COM {
607596SAlan.Adamson@Sun.COM 	return (hvio_rp_mps(dev_hdl, bdf, &mps, MPS_SET));
617596SAlan.Adamson@Sun.COM }
627596SAlan.Adamson@Sun.COM 
637596SAlan.Adamson@Sun.COM uint64_t
hvio_rp_mps(devhandle_t dev_hdl,pci_device_t bdf,int32_t * mps,int op)647596SAlan.Adamson@Sun.COM hvio_rp_mps(devhandle_t dev_hdl, pci_device_t bdf, int32_t *mps, int op)
657596SAlan.Adamson@Sun.COM {
6610595SShesha.Sreenivasamurthy@Sun.COM 	uint64_t	data, hdr, hdr_next_ptr, hdr_cap_id;
677596SAlan.Adamson@Sun.COM 	uint16_t	offset = PCI_CONF_STAT;
687596SAlan.Adamson@Sun.COM 	int		deadcount = 0;
697596SAlan.Adamson@Sun.COM 	pci_cfg_data_t	dataw;
707596SAlan.Adamson@Sun.COM 
717596SAlan.Adamson@Sun.COM 	if ((hvio_config_get(dev_hdl, bdf, PCI_CONF_VENID, 4,
727596SAlan.Adamson@Sun.COM 	    (pci_cfg_data_t *)&data)) != H_EOK)
737596SAlan.Adamson@Sun.COM 		return (H_ENOACCESS);
747596SAlan.Adamson@Sun.COM 
757596SAlan.Adamson@Sun.COM 	if ((data & 0xffff) != 0x108e)
767596SAlan.Adamson@Sun.COM 		return (H_ENOACCESS);
777596SAlan.Adamson@Sun.COM 
787596SAlan.Adamson@Sun.COM 	if ((hvio_config_get(dev_hdl, bdf, PCI_CONF_COMM, 4,
797596SAlan.Adamson@Sun.COM 	    (pci_cfg_data_t *)&hdr)) != H_EOK)
807596SAlan.Adamson@Sun.COM 		return (H_ENOACCESS);
817596SAlan.Adamson@Sun.COM 
827596SAlan.Adamson@Sun.COM 	if (!(hdr & (PCI_STAT_CAP << 16)))
837596SAlan.Adamson@Sun.COM 		return (H_ENOACCESS);
847596SAlan.Adamson@Sun.COM 
857596SAlan.Adamson@Sun.COM 	(void) hvio_config_get(dev_hdl, bdf, PCI_CONF_CAP_PTR, 4,
867596SAlan.Adamson@Sun.COM 	    (pci_cfg_data_t *)&hdr);
877596SAlan.Adamson@Sun.COM 
887596SAlan.Adamson@Sun.COM 	hdr_next_ptr = hdr & 0xFF;
897596SAlan.Adamson@Sun.COM 	hdr_cap_id = 0;
907596SAlan.Adamson@Sun.COM 
917596SAlan.Adamson@Sun.COM 	while ((hdr_next_ptr != PCI_CAP_NEXT_PTR_NULL) &&
927596SAlan.Adamson@Sun.COM 	    (hdr_cap_id != PCI_CAP_ID_PCI_E)) {
937596SAlan.Adamson@Sun.COM 
947596SAlan.Adamson@Sun.COM 		offset = hdr_next_ptr;
957596SAlan.Adamson@Sun.COM 
967596SAlan.Adamson@Sun.COM 		if (hdr_next_ptr < 0x40)
977596SAlan.Adamson@Sun.COM 			break;
987596SAlan.Adamson@Sun.COM 
997596SAlan.Adamson@Sun.COM 		(void) hvio_config_get(dev_hdl, bdf, hdr_next_ptr, 4,
1007596SAlan.Adamson@Sun.COM 		    (pci_cfg_data_t *)&hdr);
1017596SAlan.Adamson@Sun.COM 
1027596SAlan.Adamson@Sun.COM 		hdr_next_ptr = (hdr >> 8) & 0xFF;
1037596SAlan.Adamson@Sun.COM 		hdr_cap_id = hdr & 0xFF;
1047596SAlan.Adamson@Sun.COM 
1057596SAlan.Adamson@Sun.COM 		if (deadcount++ > 100)
1067596SAlan.Adamson@Sun.COM 			break;
1077596SAlan.Adamson@Sun.COM 	}
1087596SAlan.Adamson@Sun.COM 
1097596SAlan.Adamson@Sun.COM 	if (hdr_cap_id != PCI_CAP_ID_PCI_E)
1107596SAlan.Adamson@Sun.COM 		return (H_ENOACCESS);
1117596SAlan.Adamson@Sun.COM 
1127596SAlan.Adamson@Sun.COM 	if (op == MPS_SET) {
1137596SAlan.Adamson@Sun.COM 
1147596SAlan.Adamson@Sun.COM 		/* Write the MPS */
1157596SAlan.Adamson@Sun.COM 
1167596SAlan.Adamson@Sun.COM 		(void) hvio_config_get(dev_hdl, bdf, offset + PCIE_DEVCTL,
1177596SAlan.Adamson@Sun.COM 		    4, (pci_cfg_data_t *)&data);
1187596SAlan.Adamson@Sun.COM 
1197596SAlan.Adamson@Sun.COM 		data = (data & 0xffffff1f) | (*mps << 5);
1207596SAlan.Adamson@Sun.COM 
12110595SShesha.Sreenivasamurthy@Sun.COM 		dataw.qw = data;
1227596SAlan.Adamson@Sun.COM 
1237596SAlan.Adamson@Sun.COM 		(void) hvio_config_put(dev_hdl, bdf, offset + PCIE_DEVCTL,
1247596SAlan.Adamson@Sun.COM 		    4, dataw);
1257596SAlan.Adamson@Sun.COM 	} else {
1267596SAlan.Adamson@Sun.COM 
1277596SAlan.Adamson@Sun.COM 		/* Read the MPS Capabilities */
1287596SAlan.Adamson@Sun.COM 
1297596SAlan.Adamson@Sun.COM 		(void) hvio_config_get(dev_hdl, bdf, offset + PCIE_DEVCAP,
1307596SAlan.Adamson@Sun.COM 		    4, (pci_cfg_data_t *)&data);
1317596SAlan.Adamson@Sun.COM 
1327596SAlan.Adamson@Sun.COM 		*mps = data & 0x7;
1337596SAlan.Adamson@Sun.COM 	}
1347596SAlan.Adamson@Sun.COM 
1357596SAlan.Adamson@Sun.COM 	return (H_EOK);
1367596SAlan.Adamson@Sun.COM }
137