1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-15 10:17:20 +00:00
mpt.h:
	Add support for reading extended configuration pages.
mpt_cam.c:
	Do a top level topology scan on the SAS controller.  If any SATA
	device are discovered in this scan, send a passthrough FIS to set
	the write cache.  This is controllable through the following
	tunable at boot:

	hw.mpt.enable_sata_wc:
		-1 = Do not configure, use the controller default
		 0 = Disable the write cache
		 1 = Enable the write cache

	The default is -1.  This tunable is just a hack and may be
	deprecated in the future.

Turning on the write cache alleviates the write performance problems with
SATA that many people have observed.  It is not recommend for those who
value data reliability!  I cannot stress this strongly enough.  However,
it is useful in certain circumstances, and it brings the performence in line
with what a generic SATA controller running under the FreeBSD ATA driver
provides (and the ATA driver has had the WC enabled by default for years).
This commit is contained in:
Scott Long 2007-06-03 23:13:05 +00:00
parent 62ae194db2
commit 1d558d6a15
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=170252
3 changed files with 514 additions and 32 deletions

View File

@ -503,6 +503,8 @@ mpt_config_reply_handler(struct mpt_softc *mpt, request_t *req,
req->IOCStatus = le16toh(reply_frame->IOCStatus);
bcopy(&reply->Header, &cfgp->Header,
sizeof(cfgp->Header));
cfgp->ExtPageLength = reply->ExtPageLength;
cfgp->ExtPageType = reply->ExtPageType;
}
req->state &= ~REQ_STATE_QUEUED;
req->state |= REQ_STATE_DONE;
@ -1548,31 +1550,37 @@ mpt_send_ioc_init(struct mpt_softc *mpt, uint32_t who)
* Utiltity routine to read configuration headers and pages
*/
int
mpt_issue_cfg_req(struct mpt_softc *mpt, request_t *req, u_int Action,
u_int PageVersion, u_int PageLength, u_int PageNumber,
u_int PageType, uint32_t PageAddress, bus_addr_t addr,
bus_size_t len, int sleep_ok, int timeout_ms)
mpt_issue_cfg_req(struct mpt_softc *mpt, request_t *req, cfgparms_t *params,
bus_addr_t addr, bus_size_t len, int sleep_ok, int timeout_ms)
{
MSG_CONFIG *cfgp;
SGE_SIMPLE32 *se;
cfgp = req->req_vbuf;
memset(cfgp, 0, sizeof *cfgp);
cfgp->Action = Action;
cfgp->Action = params->Action;
cfgp->Function = MPI_FUNCTION_CONFIG;
cfgp->Header.PageVersion = PageVersion;
cfgp->Header.PageLength = PageLength;
cfgp->Header.PageNumber = PageNumber;
cfgp->Header.PageType = PageType;
cfgp->PageAddress = htole32(PageAddress);
cfgp->Header.PageVersion = params->PageVersion;
cfgp->Header.PageNumber = params->PageNumber;
cfgp->PageAddress = htole32(params->PageAddress);
if ((params->PageType & MPI_CONFIG_PAGETYPE_MASK) ==
MPI_CONFIG_PAGETYPE_EXTENDED) {
cfgp->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
cfgp->Header.PageLength = 0;
cfgp->ExtPageLength = htole16(params->ExtPageLength);
cfgp->ExtPageType = params->ExtPageType;
} else {
cfgp->Header.PageType = params->PageType;
cfgp->Header.PageLength = params->PageLength;
}
se = (SGE_SIMPLE32 *)&cfgp->PageBufferSGE;
se->Address = htole32(addr);
MPI_pSGE_SET_LENGTH(se, len);
MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
MPI_SGE_FLAGS_END_OF_LIST |
((Action == MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT
|| Action == MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM)
((params->Action == MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT
|| params->Action == MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM)
? MPI_SGE_FLAGS_HOST_TO_IOC : MPI_SGE_FLAGS_IOC_TO_HOST)));
se->FlagsLength = htole32(se->FlagsLength);
cfgp->MsgContext = htole32(req->index | MPT_REPLY_HANDLER_CONFIG);
@ -1583,6 +1591,113 @@ mpt_issue_cfg_req(struct mpt_softc *mpt, request_t *req, u_int Action,
sleep_ok, timeout_ms));
}
int
mpt_read_extcfg_header(struct mpt_softc *mpt, int PageVersion, int PageNumber,
uint32_t PageAddress, int ExtPageType,
CONFIG_EXTENDED_PAGE_HEADER *rslt,
int sleep_ok, int timeout_ms)
{
request_t *req;
cfgparms_t params;
MSG_CONFIG_REPLY *cfgp;
int error;
req = mpt_get_request(mpt, sleep_ok);
if (req == NULL) {
mpt_prt(mpt, "mpt_extread_cfg_header: Get request failed!\n");
return (ENOMEM);
}
params.Action = MPI_CONFIG_ACTION_PAGE_HEADER;
params.PageVersion = PageVersion;
params.PageLength = 0;
params.PageNumber = PageNumber;
params.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
params.PageAddress = PageAddress;
params.ExtPageType = ExtPageType;
params.ExtPageLength = 0;
error = mpt_issue_cfg_req(mpt, req, &params, /*addr*/0, /*len*/0,
sleep_ok, timeout_ms);
if (error != 0) {
/*
* Leave the request. Without resetting the chip, it's
* still owned by it and we'll just get into trouble
* freeing it now. Mark it as abandoned so that if it
* shows up later it can be freed.
*/
mpt_prt(mpt, "read_extcfg_header timed out\n");
return (ETIMEDOUT);
}
switch (req->IOCStatus & MPI_IOCSTATUS_MASK) {
case MPI_IOCSTATUS_SUCCESS:
cfgp = req->req_vbuf;
rslt->PageVersion = cfgp->Header.PageVersion;
rslt->PageNumber = cfgp->Header.PageNumber;
rslt->PageType = cfgp->Header.PageType;
rslt->ExtPageLength = cfgp->ExtPageLength;
rslt->ExtPageType = cfgp->ExtPageType;
error = 0;
break;
case MPI_IOCSTATUS_CONFIG_INVALID_PAGE:
mpt_lprt(mpt, MPT_PRT_DEBUG,
"Invalid Page Type %d Number %d Addr 0x%0x\n",
MPI_CONFIG_PAGETYPE_EXTENDED, PageNumber, PageAddress);
error = EINVAL;
break;
default:
mpt_prt(mpt, "mpt_read_extcfg_header: Config Info Status %x\n",
req->IOCStatus);
error = EIO;
break;
}
mpt_free_request(mpt, req);
return (error);
}
int
mpt_read_extcfg_page(struct mpt_softc *mpt, int Action, uint32_t PageAddress,
CONFIG_EXTENDED_PAGE_HEADER *hdr, void *buf, size_t len,
int sleep_ok, int timeout_ms)
{
request_t *req;
cfgparms_t params;
int error;
req = mpt_get_request(mpt, sleep_ok);
if (req == NULL) {
mpt_prt(mpt, "mpt_read_cfg_page: Get request failed!\n");
return (-1);
}
params.Action = Action;
params.PageVersion = hdr->PageVersion;
params.PageLength = 0;
params.PageNumber = hdr->PageNumber;
params.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
params.PageAddress = PageAddress;
params.ExtPageType = hdr->ExtPageType;
params.ExtPageLength = hdr->ExtPageLength;
error = mpt_issue_cfg_req(mpt, req, &params,
req->req_pbuf + MPT_RQSL(mpt),
len, sleep_ok, timeout_ms);
if (error != 0) {
mpt_prt(mpt, "read_extcfg_page(%d) timed out\n", Action);
return (-1);
}
if ((req->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
mpt_prt(mpt, "mpt_read_extcfg_page: Config Info Status %x\n",
req->IOCStatus);
mpt_free_request(mpt, req);
return (-1);
}
bus_dmamap_sync(mpt->request_dmat, mpt->request_dmap,
BUS_DMASYNC_POSTREAD);
memcpy(buf, ((uint8_t *)req->req_vbuf)+MPT_RQSL(mpt), len);
mpt_free_request(mpt, req);
return (0);
}
int
mpt_read_cfg_header(struct mpt_softc *mpt, int PageType, int PageNumber,
@ -1590,6 +1705,7 @@ mpt_read_cfg_header(struct mpt_softc *mpt, int PageType, int PageNumber,
int sleep_ok, int timeout_ms)
{
request_t *req;
cfgparms_t params;
MSG_CONFIG *cfgp;
int error;
@ -1599,9 +1715,13 @@ mpt_read_cfg_header(struct mpt_softc *mpt, int PageType, int PageNumber,
return (ENOMEM);
}
error = mpt_issue_cfg_req(mpt, req, MPI_CONFIG_ACTION_PAGE_HEADER,
/*PageVersion*/0, /*PageLength*/0, PageNumber,
PageType, PageAddress, /*addr*/0, /*len*/0,
params.Action = MPI_CONFIG_ACTION_PAGE_HEADER;
params.PageVersion = 0;
params.PageLength = 0;
params.PageNumber = PageNumber;
params.PageType = PageType;
params.PageAddress = PageAddress;
error = mpt_issue_cfg_req(mpt, req, &params, /*addr*/0, /*len*/0,
sleep_ok, timeout_ms);
if (error != 0) {
/*
@ -1642,6 +1762,7 @@ mpt_read_cfg_page(struct mpt_softc *mpt, int Action, uint32_t PageAddress,
int timeout_ms)
{
request_t *req;
cfgparms_t params;
int error;
req = mpt_get_request(mpt, sleep_ok);
@ -1650,10 +1771,14 @@ mpt_read_cfg_page(struct mpt_softc *mpt, int Action, uint32_t PageAddress,
return (-1);
}
error = mpt_issue_cfg_req(mpt, req, Action, hdr->PageVersion,
hdr->PageLength, hdr->PageNumber,
hdr->PageType & MPI_CONFIG_PAGETYPE_MASK,
PageAddress, req->req_pbuf + MPT_RQSL(mpt),
params.Action = Action;
params.PageVersion = hdr->PageVersion;
params.PageLength = hdr->PageLength;
params.PageNumber = hdr->PageNumber;
params.PageType = hdr->PageType & MPI_CONFIG_PAGETYPE_MASK;
params.PageAddress = PageAddress;
error = mpt_issue_cfg_req(mpt, req, &params,
req->req_pbuf + MPT_RQSL(mpt),
len, sleep_ok, timeout_ms);
if (error != 0) {
mpt_prt(mpt, "read_cfg_page(%d) timed out\n", Action);
@ -1679,6 +1804,7 @@ mpt_write_cfg_page(struct mpt_softc *mpt, int Action, uint32_t PageAddress,
int timeout_ms)
{
request_t *req;
cfgparms_t params;
u_int hdr_attr;
int error;
@ -1708,22 +1834,21 @@ mpt_write_cfg_page(struct mpt_softc *mpt, int Action, uint32_t PageAddress,
* if you then mask them going down to issue the request.
*/
params.Action = Action;
params.PageVersion = hdr->PageVersion;
params.PageLength = hdr->PageLength;
params.PageNumber = hdr->PageNumber;
params.PageAddress = PageAddress;
#if 0
/* Restore stripped out attributes */
hdr->PageType |= hdr_attr;
error = mpt_issue_cfg_req(mpt, req, Action, hdr->PageVersion,
hdr->PageLength, hdr->PageNumber,
hdr->PageType & MPI_CONFIG_PAGETYPE_MASK,
PageAddress, req->req_pbuf + MPT_RQSL(mpt),
len, sleep_ok, timeout_ms);
params.PageType = hdr->PageType & MPI_CONFIG_PAGETYPE_MASK;
#else
error = mpt_issue_cfg_req(mpt, req, Action, hdr->PageVersion,
hdr->PageLength, hdr->PageNumber,
hdr->PageType, PageAddress,
params.PageType = hdr->PageType;
#endif
error = mpt_issue_cfg_req(mpt, req, &params,
req->req_pbuf + MPT_RQSL(mpt),
len, sleep_ok, timeout_ms);
#endif
if (error != 0) {
mpt_prt(mpt, "mpt_write_cfg_page timed out\n");
return (-1);

View File

@ -341,6 +341,17 @@ struct req_entry {
struct callout callout; /* Timeout for the request */
};
typedef struct mpt_config_params {
u_int Action;
u_int PageVersion;
u_int PageLength;
u_int PageNumber;
u_int PageType;
u_int PageAddress;
u_int ExtPageLength;
u_int ExtPageType;
} cfgparms_t;
/**************************** MPI Target State Info ***************************/
typedef struct {
@ -514,6 +525,36 @@ struct mpt_evtf_record {
LIST_HEAD(mpt_evtf_list, mpt_evtf_record);
struct mptsas_devinfo {
uint16_t dev_handle;
uint16_t parent_dev_handle;
uint16_t enclosure_handle;
uint16_t slot;
uint8_t phy_num;
uint8_t physical_port;
uint8_t target_id;
uint8_t bus;
uint64_t sas_address;
uint32_t device_info;
};
struct mptsas_phyinfo {
uint16_t handle;
uint8_t phy_num;
uint8_t port_id;
uint8_t negotiated_link_rate;
uint8_t hw_link_rate;
uint8_t programmed_link_rate;
uint8_t sas_port_add_phy;
struct mptsas_devinfo identify;
struct mptsas_devinfo attached;
};
struct mptsas_portinfo {
uint16_t num_phys;
struct mptsas_phyinfo *phy_info;
};
struct mpt_softc {
device_t dev;
#if __FreeBSD_version < 500000
@ -721,6 +762,9 @@ struct mpt_softc {
bus_dmamap_t fw_dmap; /* DMA map for firmware image */
bus_addr_t fw_phys; /* BusAddr of firmware image */
/* SAS Topology */
struct mptsas_portinfo *sas_portinfo;
/* Shutdown Event Handler. */
eventhandler_tag eh;
@ -1186,11 +1230,19 @@ void mpt_dump_reply_frame(struct mpt_softc *mpt,
void mpt_set_config_regs(struct mpt_softc *);
int mpt_issue_cfg_req(struct mpt_softc */*mpt*/, request_t */*req*/,
u_int /*Action*/, u_int /*PageVersion*/,
u_int /*PageLength*/, u_int /*PageNumber*/,
u_int /*PageType*/, uint32_t /*PageAddress*/,
cfgparms_t *params,
bus_addr_t /*addr*/, bus_size_t/*len*/,
int /*sleep_ok*/, int /*timeout_ms*/);
int mpt_read_extcfg_header(struct mpt_softc *mpt, int PageVersion,
int PageNumber, uint32_t PageAddress,
int ExtPageType,
CONFIG_EXTENDED_PAGE_HEADER *rslt,
int sleep_ok, int timeout_ms);
int mpt_read_extcfg_page(struct mpt_softc *mpt, int Action,
uint32_t PageAddress,
CONFIG_EXTENDED_PAGE_HEADER *hdr,
void *buf, size_t len, int sleep_ok,
int timeout_ms);
int mpt_read_cfg_header(struct mpt_softc *, int /*PageType*/,
int /*PageNumber*/,
uint32_t /*PageAddress*/,

View File

@ -104,6 +104,7 @@ __FBSDID("$FreeBSD$");
#include "dev/mpt/mpilib/mpi_init.h"
#include "dev/mpt/mpilib/mpi_targ.h"
#include "dev/mpt/mpilib/mpi_fc.h"
#include "dev/mpt/mpilib/mpi_sas.h"
#if __FreeBSD_version >= 500000
#include <sys/sysctl.h>
#endif
@ -159,10 +160,12 @@ mpt_scsi_tgt_tsk_mgmt(struct mpt_softc *, request_t *, mpt_task_mgmt_t,
static void mpt_tgt_dump_tgt_state(struct mpt_softc *, request_t *);
static void mpt_tgt_dump_req_state(struct mpt_softc *, request_t *);
static mpt_reply_handler_t mpt_scsi_tgt_reply_handler;
static mpt_reply_handler_t mpt_sata_pass_reply_handler;
static uint32_t scsi_io_handler_id = MPT_HANDLER_ID_NONE;
static uint32_t scsi_tmf_handler_id = MPT_HANDLER_ID_NONE;
static uint32_t fc_els_handler_id = MPT_HANDLER_ID_NONE;
static uint32_t sata_pass_handler_id = MPT_HANDLER_ID_NONE;
static mpt_probe_handler_t mpt_cam_probe;
static mpt_attach_handler_t mpt_cam_attach;
@ -187,6 +190,9 @@ static struct mpt_personality mpt_cam_personality =
DECLARE_MPT_PERSONALITY(mpt_cam, SI_ORDER_SECOND);
MODULE_DEPEND(mpt_cam, cam, 1, 1, 1);
int mpt_enable_sata_wc = -1;
TUNABLE_INT("hw.mpt.enable_sata_wc", &mpt_enable_sata_wc);
int
mpt_cam_probe(struct mpt_softc *mpt)
{
@ -273,6 +279,16 @@ mpt_cam_attach(struct mpt_softc *mpt)
}
}
if (mpt->is_sas) {
handler.reply_handler = mpt_sata_pass_reply_handler;
error = mpt_register_handler(mpt, MPT_HANDLER_REPLY, handler,
&sata_pass_handler_id);
if (error != 0) {
MPT_UNLOCK(mpt);
goto cleanup;
}
}
/*
* We keep one request reserved for timeout TMF requests.
*/
@ -584,24 +600,310 @@ mpt_set_initial_config_fc(struct mpt_softc *mpt)
return (0);
}
static int
mptsas_sas_io_unit_pg0(struct mpt_softc *mpt, struct mptsas_portinfo *portinfo)
{
ConfigExtendedPageHeader_t hdr;
struct mptsas_phyinfo *phyinfo;
SasIOUnitPage0_t *buffer;
int error, len, i;
error = mpt_read_extcfg_header(mpt, MPI_SASIOUNITPAGE0_PAGEVERSION,
0, 0, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT,
&hdr, 0, 10000);
if (error)
goto out;
if (hdr.ExtPageLength == 0) {
error = ENXIO;
goto out;
}
len = hdr.ExtPageLength * 4;
buffer = malloc(len, M_DEVBUF, M_NOWAIT|M_ZERO);
if (buffer == NULL) {
error = ENOMEM;
goto out;
}
error = mpt_read_extcfg_page(mpt, MPI_CONFIG_ACTION_PAGE_READ_CURRENT,
0, &hdr, buffer, len, 0, 10000);
if (error) {
free(buffer, M_DEVBUF);
goto out;
}
portinfo->num_phys = buffer->NumPhys;
portinfo->phy_info = malloc(sizeof(*portinfo->phy_info) *
portinfo->num_phys, M_DEVBUF, M_NOWAIT|M_ZERO);
if (portinfo->phy_info == NULL) {
free(buffer, M_DEVBUF);
error = ENOMEM;
goto out;
}
for (i = 0; i < portinfo->num_phys; i++) {
phyinfo = &portinfo->phy_info[i];
phyinfo->phy_num = i;
phyinfo->port_id = buffer->PhyData[i].Port;
phyinfo->negotiated_link_rate =
buffer->PhyData[i].NegotiatedLinkRate;
phyinfo->handle =
le16toh(buffer->PhyData[i].ControllerDevHandle);
}
free(buffer, M_DEVBUF);
out:
return (error);
}
static int
mptsas_sas_phy_pg0(struct mpt_softc *mpt, struct mptsas_phyinfo *phy_info,
uint32_t form, uint32_t form_specific)
{
ConfigExtendedPageHeader_t hdr;
SasPhyPage0_t *buffer;
int error;
error = mpt_read_extcfg_header(mpt, MPI_SASPHY0_PAGEVERSION, 0, 0,
MPI_CONFIG_EXTPAGETYPE_SAS_PHY, &hdr,
0, 10000);
if (error)
goto out;
if (hdr.ExtPageLength == 0) {
error = ENXIO;
goto out;
}
buffer = malloc(sizeof(SasPhyPage0_t), M_DEVBUF, M_NOWAIT|M_ZERO);
if (buffer == NULL) {
error = ENOMEM;
goto out;
}
error = mpt_read_extcfg_page(mpt, MPI_CONFIG_ACTION_PAGE_READ_CURRENT,
form + form_specific, &hdr, buffer,
sizeof(SasPhyPage0_t), 0, 10000);
if (error) {
free(buffer, M_DEVBUF);
goto out;
}
phy_info->hw_link_rate = buffer->HwLinkRate;
phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
phy_info->identify.dev_handle = le16toh(buffer->OwnerDevHandle);
phy_info->attached.dev_handle = le16toh(buffer->AttachedDevHandle);
free(buffer, M_DEVBUF);
out:
return (error);
}
static int
mptsas_sas_device_pg0(struct mpt_softc *mpt, struct mptsas_devinfo *device_info,
uint32_t form, uint32_t form_specific)
{
ConfigExtendedPageHeader_t hdr;
SasDevicePage0_t *buffer;
uint64_t sas_address;
int error = 0;
bzero(device_info, sizeof(*device_info));
error = mpt_read_extcfg_header(mpt, MPI_SASDEVICE0_PAGEVERSION, 0, 0,
MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE,
&hdr, 0, 10000);
if (error)
goto out;
if (hdr.ExtPageLength == 0) {
error = ENXIO;
goto out;
}
buffer = malloc(sizeof(SasDevicePage0_t), M_DEVBUF, M_NOWAIT|M_ZERO);
if (buffer == NULL) {
error = ENOMEM;
goto out;
}
error = mpt_read_extcfg_page(mpt, MPI_CONFIG_ACTION_PAGE_READ_CURRENT,
form + form_specific, &hdr, buffer,
sizeof(SasDevicePage0_t), 0, 10000);
if (error) {
free(buffer, M_DEVBUF);
goto out;
}
device_info->dev_handle = le16toh(buffer->DevHandle);
device_info->parent_dev_handle = le16toh(buffer->ParentDevHandle);
device_info->enclosure_handle = le16toh(buffer->EnclosureHandle);
device_info->slot = le16toh(buffer->Slot);
device_info->phy_num = buffer->PhyNum;
device_info->physical_port = buffer->PhysicalPort;
device_info->target_id = buffer->TargetID;
device_info->bus = buffer->Bus;
bcopy(&buffer->SASAddress, &sas_address, sizeof(uint64_t));
device_info->sas_address = le64toh(sas_address);
device_info->device_info = le32toh(buffer->DeviceInfo);
free(buffer, M_DEVBUF);
out:
return (error);
}
/*
* Read SAS configuration information. Nothing to do yet.
*/
static int
mpt_read_config_info_sas(struct mpt_softc *mpt)
{
struct mptsas_portinfo *portinfo;
struct mptsas_phyinfo *phyinfo;
int error, i;
portinfo = malloc(sizeof(*portinfo), M_DEVBUF, M_NOWAIT|M_ZERO);
if (portinfo == NULL)
return (ENOMEM);
error = mptsas_sas_io_unit_pg0(mpt, portinfo);
if (error) {
free(portinfo, M_DEVBUF);
return (0);
}
for (i = 0; i < portinfo->num_phys; i++) {
phyinfo = &portinfo->phy_info[i];
error = mptsas_sas_phy_pg0(mpt, phyinfo,
(MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
if (error)
break;
error = mptsas_sas_device_pg0(mpt, &phyinfo->identify,
(MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
phyinfo->handle);
if (error)
break;
phyinfo->identify.phy_num = phyinfo->phy_num = i;
if (phyinfo->attached.dev_handle)
error = mptsas_sas_device_pg0(mpt,
&phyinfo->attached,
(MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
phyinfo->attached.dev_handle);
if (error)
break;
}
mpt->sas_portinfo = portinfo;
free(portinfo, M_DEVBUF);
return (0);
}
static void
mptsas_set_sata_wc(struct mpt_softc *mpt, struct mptsas_devinfo *devinfo,
int enabled)
{
SataPassthroughRequest_t *pass;
request_t *req;
int error, status;
req = mpt_get_request(mpt, 0);
if (req == NULL)
return;
pass = req->req_vbuf;
bzero(pass, sizeof(SataPassthroughRequest_t));
pass->Function = MPI_FUNCTION_SATA_PASSTHROUGH;
pass->TargetID = devinfo->target_id;
pass->Bus = devinfo->bus;
pass->PassthroughFlags = 0;
pass->ConnectionRate = MPI_SATA_PT_REQ_CONNECT_RATE_NEGOTIATED;
pass->DataLength = 0;
pass->MsgContext = htole32(req->index | sata_pass_handler_id);
pass->CommandFIS[0] = 0x27;
pass->CommandFIS[1] = 0x80;
pass->CommandFIS[2] = 0xef;
pass->CommandFIS[3] = (enabled) ? 0x02 : 0x82;
pass->CommandFIS[7] = 0x40;
pass->CommandFIS[15] = 0x08;
mpt_check_doorbell(mpt);
mpt_send_cmd(mpt, req);
error = mpt_wait_req(mpt, req, REQ_STATE_DONE, REQ_STATE_DONE, 0,
10 * 1000);
if (error) {
mpt_free_request(mpt, req);
printf("error %d sending passthrough\n", error);
return;
}
status = le16toh(req->IOCStatus);
if (status != MPI_IOCSTATUS_SUCCESS) {
mpt_free_request(mpt, req);
printf("IOCSTATUS %d\n", status);
return;
}
mpt_free_request(mpt, req);
}
/*
* Set SAS configuration information. Nothing to do yet.
*/
static int
mpt_set_initial_config_sas(struct mpt_softc *mpt)
{
struct mptsas_phyinfo *phyinfo;
int i;
if ((mpt_enable_sata_wc != -1) && (mpt->sas_portinfo != NULL)) {
for (i = 0; i < mpt->sas_portinfo->num_phys; i++) {
phyinfo = &mpt->sas_portinfo->phy_info[i];
if (phyinfo->attached.dev_handle == 0)
continue;
if ((phyinfo->attached.device_info &
MPI_SAS_DEVICE_INFO_SATA_DEVICE) == 0)
continue;
if (bootverbose)
device_printf(mpt->dev,
"%sabling SATA WC on phy %d\n",
(mpt_enable_sata_wc) ? "En" : "Dis", i);
mptsas_set_sata_wc(mpt, &phyinfo->attached,
mpt_enable_sata_wc);
}
}
return (0);
}
static int
mpt_sata_pass_reply_handler(struct mpt_softc *mpt, request_t *req,
uint32_t reply_desc, MSG_DEFAULT_REPLY *reply_frame)
{
if (req != NULL) {
if (reply_frame != NULL) {
MSG_SATA_PASSTHROUGH_REQUEST *pass;
MSG_SATA_PASSTHROUGH_REPLY *reply;
pass = (MSG_SATA_PASSTHROUGH_REQUEST *)req->req_vbuf;
reply = (MSG_SATA_PASSTHROUGH_REPLY *)reply_frame;
req->IOCStatus = le16toh(reply_frame->IOCStatus);
}
req->state &= ~REQ_STATE_QUEUED;
req->state |= REQ_STATE_DONE;
TAILQ_REMOVE(&mpt->request_pending_list, req, links);
if ((req->state & REQ_STATE_NEED_WAKEUP) != 0) {
wakeup(req);
} else if ((req->state & REQ_STATE_TIMEDOUT) != 0) {
/*
* Whew- we can free this request (late completion)
*/
mpt_free_request(mpt, req);
}
}
return (TRUE);
}
/*
* Read SCSI configuration information
*/
@ -888,6 +1190,9 @@ mpt_cam_detach(struct mpt_softc *mpt)
handler.reply_handler = mpt_scsi_tgt_reply_handler;
mpt_deregister_handler(mpt, MPT_HANDLER_REPLY, handler,
mpt->scsi_tgt_handler_id);
handler.reply_handler = mpt_sata_pass_reply_handler;
mpt_deregister_handler(mpt, MPT_HANDLER_REPLY, handler,
sata_pass_handler_id);
if (mpt->tmf_req != NULL) {
mpt->tmf_req->state = REQ_STATE_ALLOCATED;