This patch adds the feature to provide PCI information via IOCTL query.

Reviewed by:	ambrisko
MFC after:	2 weeks
Sponsored by:	AVAGO Technologies
This commit is contained in:
kadesai 2015-05-06 10:32:27 +00:00
parent 6b7074e362
commit 89cb6b04b0
3 changed files with 217 additions and 11 deletions

View File

@ -87,6 +87,8 @@ mrsas_get_ctrl_info(struct mrsas_softc *sc,
static int
mrsas_issue_blocked_abort_cmd(struct mrsas_softc *sc,
struct mrsas_mfi_cmd *cmd_to_abort);
static struct mrsas_softc *mrsas_get_softc_instance(struct cdev *dev,
u_long cmd, caddr_t arg);
u_int32_t mrsas_read_reg(struct mrsas_softc *sc, int offset);
u_int8_t
mrsas_build_mptmfi_passthru(struct mrsas_softc *sc,
@ -1231,6 +1233,39 @@ mrsas_resume(device_t dev)
return (0);
}
/**
* mrsas_get_softc_instance: Find softc instance based on cmd type
*
* This function will return softc instance based on cmd type.
* In some case, application fire ioctl on required management instance and
* do not provide host_no. Use cdev->si_drv1 to get softc instance for those
* case, else get the softc instance from host_no provided by application in
* user data.
*/
static struct mrsas_softc *
mrsas_get_softc_instance(struct cdev *dev, u_long cmd, caddr_t arg)
{
struct mrsas_softc *sc = NULL;
struct mrsas_iocpacket *user_ioc = (struct mrsas_iocpacket *)arg;
if (cmd == MRSAS_IOC_GET_PCI_INFO){
sc = dev->si_drv1;
} else {
/* get the Host number & the softc from data sent by the Application */
sc = mrsas_mgmt_info.sc_ptr[user_ioc->host_no];
if ((user_ioc->host_no >= mrsas_mgmt_info.max_index) || (sc == NULL)) {
if (sc == NULL)
mrsas_dprint(sc, MRSAS_FAULT,
"There is no Controller number %d .\n", user_ioc->host_no);
else
mrsas_dprint(sc, MRSAS_FAULT,
"Invalid Controller number %d .\n", user_ioc->host_no);
}
}
return sc;
}
/*
* mrsas_ioctl: IOCtl commands entry point.
*
@ -1243,19 +1278,12 @@ mrsas_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag,
{
struct mrsas_softc *sc;
int ret = 0, i = 0;
MRSAS_DRV_PCI_INFORMATION *pciDrvInfo;
struct mrsas_iocpacket *user_ioc = (struct mrsas_iocpacket *)arg;
/* get the Host number & the softc from data sent by the Application */
sc = mrsas_mgmt_info.sc_ptr[user_ioc->host_no];
if ((mrsas_mgmt_info.max_index == user_ioc->host_no) || (sc == NULL)) {
printf("Please check the controller number\n");
if (sc == NULL)
printf("There is NO such Host no. %d\n", user_ioc->host_no);
sc = mrsas_get_softc_instance(dev, cmd, arg);
if (!sc)
return ENOENT;
}
if (sc->remove_in_progress) {
mrsas_dprint(sc, MRSAS_INFO,
"Driver remove or shutdown called.\n");
@ -1299,6 +1327,22 @@ mrsas_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag,
case MRSAS_IOC_SCAN_BUS:
ret = mrsas_bus_scan(sc);
break;
case MRSAS_IOC_GET_PCI_INFO:
pciDrvInfo = (MRSAS_DRV_PCI_INFORMATION *)arg;
memset (pciDrvInfo, 0, sizeof(MRSAS_DRV_PCI_INFORMATION));
pciDrvInfo->busNumber = pci_get_bus(sc->mrsas_dev);
pciDrvInfo->deviceNumber = pci_get_slot(sc->mrsas_dev);
pciDrvInfo->functionNumber = pci_get_function(sc->mrsas_dev);
pciDrvInfo->domainID = pci_get_domain(sc->mrsas_dev);
mrsas_dprint (sc, MRSAS_INFO, "pci bus no: %d,"
"pci device no: %d, pci function no: %d,"
"pci domain ID: %d\n",
pciDrvInfo->busNumber, pciDrvInfo->deviceNumber,
pciDrvInfo->functionNumber, pciDrvInfo->domainID);
ret = 0;
break;
default:
mrsas_dprint(sc, MRSAS_TRACE, "IOCTL command 0x%lx is not handled\n", cmd);
ret = ENOENT;

View File

@ -2413,6 +2413,167 @@ struct mrsas_mgmt_info {
int max_index;
};
#define PCI_TYPE0_ADDRESSES 6
#define PCI_TYPE1_ADDRESSES 2
#define PCI_TYPE2_ADDRESSES 5
typedef struct _MRSAS_DRV_PCI_COMMON_HEADER
{
u_int16_t vendorID; // (ro)
u_int16_t deviceID; // (ro)
u_int16_t command; // Device control
u_int16_t status;
u_int8_t revisionID; // (ro)
u_int8_t progIf; // (ro)
u_int8_t subClass; // (ro)
u_int8_t baseClass; // (ro)
u_int8_t cacheLineSize; // (ro+)
u_int8_t latencyTimer; // (ro+)
u_int8_t headerType; // (ro)
u_int8_t bist; // Built in self test
union
{
struct _MRSAS_DRV_PCI_HEADER_TYPE_0
{
u_int32_t baseAddresses[PCI_TYPE0_ADDRESSES];
u_int32_t cis;
u_int16_t subVendorID;
u_int16_t subSystemID;
u_int32_t romBaseAddress;
u_int8_t capabilitiesPtr;
u_int8_t reserved1[3];
u_int32_t reserved2;
u_int8_t interruptLine;
u_int8_t interruptPin; // (ro)
u_int8_t minimumGrant; // (ro)
u_int8_t maximumLatency; // (ro)
} type0;
/*
* PCI to PCI Bridge
*/
struct _MRSAS_DRV_PCI_HEADER_TYPE_1
{
u_int32_t baseAddresses[PCI_TYPE1_ADDRESSES];
u_int8_t primaryBus;
u_int8_t secondaryBus;
u_int8_t subordinateBus;
u_int8_t secondaryLatency;
u_int8_t ioBase;
u_int8_t ioLimit;
u_int16_t secondaryStatus;
u_int16_t memoryBase;
u_int16_t memoryLimit;
u_int16_t prefetchBase;
u_int16_t prefetchLimit;
u_int32_t prefetchBaseUpper32;
u_int32_t prefetchLimitUpper32;
u_int16_t ioBaseUpper16;
u_int16_t ioLimitUpper16;
u_int8_t capabilitiesPtr;
u_int8_t reserved1[3];
u_int32_t romBaseAddress;
u_int8_t interruptLine;
u_int8_t interruptPin;
u_int16_t bridgeControl;
} type1;
/*
* PCI to CARDBUS Bridge
*/
struct _MRSAS_DRV_PCI_HEADER_TYPE_2
{
u_int32_t socketRegistersBaseAddress;
u_int8_t capabilitiesPtr;
u_int8_t reserved;
u_int16_t secondaryStatus;
u_int8_t primaryBus;
u_int8_t secondaryBus;
u_int8_t subordinateBus;
u_int8_t secondaryLatency;
struct
{
u_int32_t base;
u_int32_t limit;
} range[PCI_TYPE2_ADDRESSES-1];
u_int8_t interruptLine;
u_int8_t interruptPin;
u_int16_t bridgeControl;
} type2;
} u;
} MRSAS_DRV_PCI_COMMON_HEADER, *PMRSAS_DRV_PCI_COMMON_HEADER;
#define MRSAS_DRV_PCI_COMMON_HEADER_SIZE sizeof(MRSAS_DRV_PCI_COMMON_HEADER) //64 bytes
typedef struct _MRSAS_DRV_PCI_LINK_CAPABILITY
{
union
{
struct
{
u_int32_t linkSpeed :4;
u_int32_t linkWidth :6;
u_int32_t aspmSupport :2;
u_int32_t losExitLatency :3;
u_int32_t l1ExitLatency :3;
u_int32_t rsvdp :6;
u_int32_t portNumber :8;
}bits;
u_int32_t asUlong;
}u;
}MRSAS_DRV_PCI_LINK_CAPABILITY, *PMRSAS_DRV_PCI_LINK_CAPABILITY;
#define MRSAS_DRV_PCI_LINK_CAPABILITY_SIZE sizeof(MRSAS_DRV_PCI_LINK_CAPABILITY)
typedef struct _MRSAS_DRV_PCI_LINK_STATUS_CAPABILITY
{
union
{
struct
{
u_int16_t linkSpeed :4;
u_int16_t negotiatedLinkWidth :6;
u_int16_t linkTrainingError :1;
u_int16_t linkTraning :1;
u_int16_t slotClockConfig :1;
u_int16_t rsvdZ :3;
}bits;
u_int16_t asUshort;
}u;
u_int16_t reserved;
} MRSAS_DRV_PCI_LINK_STATUS_CAPABILITY, *PMRSAS_DRV_PCI_LINK_STATUS_CAPABILITY;
#define MRSAS_DRV_PCI_LINK_STATUS_CAPABILITY_SIZE sizeof(MRSAS_DRV_PCI_LINK_STATUS_CAPABILITY)
typedef struct _MRSAS_DRV_PCI_CAPABILITIES
{
MRSAS_DRV_PCI_LINK_CAPABILITY linkCapability;
MRSAS_DRV_PCI_LINK_STATUS_CAPABILITY linkStatusCapability;
}MRSAS_DRV_PCI_CAPABILITIES, *PMRSAS_DRV_PCI_CAPABILITIES;
#define MRSAS_DRV_PCI_CAPABILITIES_SIZE sizeof(MRSAS_DRV_PCI_CAPABILITIES)
/* PCI information */
typedef struct _MRSAS_DRV_PCI_INFORMATION
{
u_int32_t busNumber;
u_int8_t deviceNumber;
u_int8_t functionNumber;
u_int8_t interruptVector;
u_int8_t reserved1;
MRSAS_DRV_PCI_COMMON_HEADER pciHeaderInfo;
MRSAS_DRV_PCI_CAPABILITIES capability;
u_int32_t domainID;
u_int8_t reserved2[28];
}MRSAS_DRV_PCI_INFORMATION, *PMRSAS_DRV_PCI_INFORMATION;
/*******************************************************************
* per-instance data
********************************************************************/

View File

@ -64,6 +64,7 @@ __FBSDID("$FreeBSD$");
* into a somewhat unique, 32-bit value.
*/
#define MRSAS_IOC_GET_PCI_INFO _IOR('M', 7, MRSAS_DRV_PCI_INFORMATION)
#define MRSAS_IOC_FIRMWARE_PASS_THROUGH64 _IOWR('M', 1, struct mrsas_iocpacket)
#ifdef COMPAT_FREEBSD32
#define MRSAS_IOC_FIRMWARE_PASS_THROUGH32 _IOWR('M', 1, struct mrsas_iocpacket32)