10114761dSAlan Adamson, SD OSSD /*
20114761dSAlan Adamson, SD OSSD * CDDL HEADER START
30114761dSAlan Adamson, SD OSSD *
40114761dSAlan Adamson, SD OSSD * The contents of this file are subject to the terms of the
50114761dSAlan Adamson, SD OSSD * Common Development and Distribution License (the "License").
60114761dSAlan Adamson, SD OSSD * You may not use this file except in compliance with the License.
70114761dSAlan Adamson, SD OSSD *
80114761dSAlan Adamson, SD OSSD * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90114761dSAlan Adamson, SD OSSD * or http://www.opensolaris.org/os/licensing.
100114761dSAlan Adamson, SD OSSD * See the License for the specific language governing permissions
110114761dSAlan Adamson, SD OSSD * and limitations under the License.
120114761dSAlan Adamson, SD OSSD *
130114761dSAlan Adamson, SD OSSD * When distributing Covered Code, include this CDDL HEADER in each
140114761dSAlan Adamson, SD OSSD * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150114761dSAlan Adamson, SD OSSD * If applicable, add the following below this CDDL HEADER, with the
160114761dSAlan Adamson, SD OSSD * fields enclosed by brackets "[]" replaced with your own identifying
170114761dSAlan Adamson, SD OSSD * information: Portions Copyright [yyyy] [name of copyright owner]
180114761dSAlan Adamson, SD OSSD *
190114761dSAlan Adamson, SD OSSD * CDDL HEADER END
200114761dSAlan Adamson, SD OSSD */
210114761dSAlan Adamson, SD OSSD /*
22abdf5d9aSShesha Sreenivasamurthy * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
230114761dSAlan Adamson, SD OSSD * Use is subject to license terms.
240114761dSAlan Adamson, SD OSSD */
250114761dSAlan Adamson, SD OSSD
260114761dSAlan Adamson, SD OSSD #include <sys/types.h>
270114761dSAlan Adamson, SD OSSD #include <sys/sysmacros.h>
280114761dSAlan Adamson, SD OSSD #include <sys/ddi.h>
290114761dSAlan Adamson, SD OSSD #include <sys/async.h>
300114761dSAlan Adamson, SD OSSD #include <sys/sunddi.h>
310114761dSAlan Adamson, SD OSSD #include <sys/ddifm.h>
320114761dSAlan Adamson, SD OSSD #include <sys/fm/protocol.h>
330114761dSAlan Adamson, SD OSSD #include <sys/vmem.h>
340114761dSAlan Adamson, SD OSSD #include <sys/intr.h>
350114761dSAlan Adamson, SD OSSD #include <sys/ivintr.h>
360114761dSAlan Adamson, SD OSSD #include <sys/errno.h>
370114761dSAlan Adamson, SD OSSD #include <sys/hypervisor_api.h>
380114761dSAlan Adamson, SD OSSD #include <sys/hsvc.h>
39*c0da6274SZhi-Jun Robin Fu #include <sys/pci_cfgacc.h>
40*c0da6274SZhi-Jun Robin Fu #include <sys/pci_cfgacc_4v.h>
410114761dSAlan Adamson, SD OSSD #include <px_obj.h>
420114761dSAlan Adamson, SD OSSD #include <sys/machsystm.h>
430114761dSAlan Adamson, SD OSSD #include "px_lib4v.h"
440114761dSAlan Adamson, SD OSSD
450114761dSAlan Adamson, SD OSSD #define MPS_SET 0
460114761dSAlan Adamson, SD OSSD #define MPS_GET 1
470114761dSAlan Adamson, SD OSSD
480114761dSAlan Adamson, SD OSSD static uint64_t hvio_rp_mps(devhandle_t dev_hdl, pci_device_t bdf, int32_t *mps,
490114761dSAlan Adamson, SD OSSD int op);
500114761dSAlan Adamson, SD OSSD
510114761dSAlan Adamson, SD OSSD uint64_t
hvio_get_rp_mps_cap(devhandle_t dev_hdl,pci_device_t bdf,int32_t * mps_cap)520114761dSAlan Adamson, SD OSSD hvio_get_rp_mps_cap(devhandle_t dev_hdl, pci_device_t bdf, int32_t *mps_cap)
530114761dSAlan Adamson, SD OSSD {
540114761dSAlan Adamson, SD OSSD return (hvio_rp_mps(dev_hdl, bdf, mps_cap, MPS_GET));
550114761dSAlan Adamson, SD OSSD }
560114761dSAlan Adamson, SD OSSD
570114761dSAlan Adamson, SD OSSD uint64_t
hvio_set_rp_mps(devhandle_t dev_hdl,pci_device_t bdf,int32_t mps)580114761dSAlan Adamson, SD OSSD hvio_set_rp_mps(devhandle_t dev_hdl, pci_device_t bdf, int32_t mps)
590114761dSAlan Adamson, SD OSSD {
600114761dSAlan Adamson, SD OSSD return (hvio_rp_mps(dev_hdl, bdf, &mps, MPS_SET));
610114761dSAlan Adamson, SD OSSD }
620114761dSAlan Adamson, SD OSSD
630114761dSAlan Adamson, SD OSSD uint64_t
hvio_rp_mps(devhandle_t dev_hdl,pci_device_t bdf,int32_t * mps,int op)640114761dSAlan Adamson, SD OSSD hvio_rp_mps(devhandle_t dev_hdl, pci_device_t bdf, int32_t *mps, int op)
650114761dSAlan Adamson, SD OSSD {
66abdf5d9aSShesha Sreenivasamurthy uint64_t data, hdr, hdr_next_ptr, hdr_cap_id;
670114761dSAlan Adamson, SD OSSD uint16_t offset = PCI_CONF_STAT;
680114761dSAlan Adamson, SD OSSD int deadcount = 0;
690114761dSAlan Adamson, SD OSSD pci_cfg_data_t dataw;
700114761dSAlan Adamson, SD OSSD
710114761dSAlan Adamson, SD OSSD if ((hvio_config_get(dev_hdl, bdf, PCI_CONF_VENID, 4,
720114761dSAlan Adamson, SD OSSD (pci_cfg_data_t *)&data)) != H_EOK)
730114761dSAlan Adamson, SD OSSD return (H_ENOACCESS);
740114761dSAlan Adamson, SD OSSD
750114761dSAlan Adamson, SD OSSD if ((data & 0xffff) != 0x108e)
760114761dSAlan Adamson, SD OSSD return (H_ENOACCESS);
770114761dSAlan Adamson, SD OSSD
780114761dSAlan Adamson, SD OSSD if ((hvio_config_get(dev_hdl, bdf, PCI_CONF_COMM, 4,
790114761dSAlan Adamson, SD OSSD (pci_cfg_data_t *)&hdr)) != H_EOK)
800114761dSAlan Adamson, SD OSSD return (H_ENOACCESS);
810114761dSAlan Adamson, SD OSSD
820114761dSAlan Adamson, SD OSSD if (!(hdr & (PCI_STAT_CAP << 16)))
830114761dSAlan Adamson, SD OSSD return (H_ENOACCESS);
840114761dSAlan Adamson, SD OSSD
850114761dSAlan Adamson, SD OSSD (void) hvio_config_get(dev_hdl, bdf, PCI_CONF_CAP_PTR, 4,
860114761dSAlan Adamson, SD OSSD (pci_cfg_data_t *)&hdr);
870114761dSAlan Adamson, SD OSSD
880114761dSAlan Adamson, SD OSSD hdr_next_ptr = hdr & 0xFF;
890114761dSAlan Adamson, SD OSSD hdr_cap_id = 0;
900114761dSAlan Adamson, SD OSSD
910114761dSAlan Adamson, SD OSSD while ((hdr_next_ptr != PCI_CAP_NEXT_PTR_NULL) &&
920114761dSAlan Adamson, SD OSSD (hdr_cap_id != PCI_CAP_ID_PCI_E)) {
930114761dSAlan Adamson, SD OSSD
940114761dSAlan Adamson, SD OSSD offset = hdr_next_ptr;
950114761dSAlan Adamson, SD OSSD
960114761dSAlan Adamson, SD OSSD if (hdr_next_ptr < 0x40)
970114761dSAlan Adamson, SD OSSD break;
980114761dSAlan Adamson, SD OSSD
990114761dSAlan Adamson, SD OSSD (void) hvio_config_get(dev_hdl, bdf, hdr_next_ptr, 4,
1000114761dSAlan Adamson, SD OSSD (pci_cfg_data_t *)&hdr);
1010114761dSAlan Adamson, SD OSSD
1020114761dSAlan Adamson, SD OSSD hdr_next_ptr = (hdr >> 8) & 0xFF;
1030114761dSAlan Adamson, SD OSSD hdr_cap_id = hdr & 0xFF;
1040114761dSAlan Adamson, SD OSSD
1050114761dSAlan Adamson, SD OSSD if (deadcount++ > 100)
1060114761dSAlan Adamson, SD OSSD break;
1070114761dSAlan Adamson, SD OSSD }
1080114761dSAlan Adamson, SD OSSD
1090114761dSAlan Adamson, SD OSSD if (hdr_cap_id != PCI_CAP_ID_PCI_E)
1100114761dSAlan Adamson, SD OSSD return (H_ENOACCESS);
1110114761dSAlan Adamson, SD OSSD
1120114761dSAlan Adamson, SD OSSD if (op == MPS_SET) {
1130114761dSAlan Adamson, SD OSSD
1140114761dSAlan Adamson, SD OSSD /* Write the MPS */
1150114761dSAlan Adamson, SD OSSD
1160114761dSAlan Adamson, SD OSSD (void) hvio_config_get(dev_hdl, bdf, offset + PCIE_DEVCTL,
1170114761dSAlan Adamson, SD OSSD 4, (pci_cfg_data_t *)&data);
1180114761dSAlan Adamson, SD OSSD
1190114761dSAlan Adamson, SD OSSD data = (data & 0xffffff1f) | (*mps << 5);
1200114761dSAlan Adamson, SD OSSD
121abdf5d9aSShesha Sreenivasamurthy dataw.qw = data;
1220114761dSAlan Adamson, SD OSSD
1230114761dSAlan Adamson, SD OSSD (void) hvio_config_put(dev_hdl, bdf, offset + PCIE_DEVCTL,
1240114761dSAlan Adamson, SD OSSD 4, dataw);
1250114761dSAlan Adamson, SD OSSD } else {
1260114761dSAlan Adamson, SD OSSD
1270114761dSAlan Adamson, SD OSSD /* Read the MPS Capabilities */
1280114761dSAlan Adamson, SD OSSD
1290114761dSAlan Adamson, SD OSSD (void) hvio_config_get(dev_hdl, bdf, offset + PCIE_DEVCAP,
1300114761dSAlan Adamson, SD OSSD 4, (pci_cfg_data_t *)&data);
1310114761dSAlan Adamson, SD OSSD
1320114761dSAlan Adamson, SD OSSD *mps = data & 0x7;
1330114761dSAlan Adamson, SD OSSD }
1340114761dSAlan Adamson, SD OSSD
1350114761dSAlan Adamson, SD OSSD return (H_EOK);
1360114761dSAlan Adamson, SD OSSD }
137