Flesh out support for SAS1078 and SAS1078DE (which are said to actually
be the same chip): - The I/O port resource may not be available with these. However, given that we actually only need this resource for some controllers that require their firmware to be up- and downloaded (which excludes the SAS1078{,DE}) just handle failure to allocate this resource gracefully when possible. While at it, generally put non-fatal resource allocation failures under bootverbose. - SAS1078{,DE} use a different hard reset protocol. - Add workarounds for the 36GB physical address limitation of scatter/ gather elements of these controllers. Tested by: Slawa Olhovchenkov PR: 149220 (remaining part)
This commit is contained in:
parent
ceec1ea79a
commit
04016bcf93
@ -1053,6 +1053,12 @@ mpt_hard_reset(struct mpt_softc *mpt)
|
||||
|
||||
mpt_lprt(mpt, MPT_PRT_DEBUG, "hard reset\n");
|
||||
|
||||
if (mpt->is_1078) {
|
||||
mpt_write(mpt, MPT_OFFSET_RESET_1078, 0x07);
|
||||
DELAY(1000);
|
||||
return;
|
||||
}
|
||||
|
||||
error = mpt_enable_diag_mode(mpt);
|
||||
if (error) {
|
||||
mpt_prt(mpt, "WARNING - Could not enter diagnostic mode !\n");
|
||||
@ -2450,6 +2456,11 @@ mpt_download_fw(struct mpt_softc *mpt)
|
||||
uint32_t ext_offset;
|
||||
uint32_t data;
|
||||
|
||||
if (mpt->pci_pio_reg == NULL) {
|
||||
mpt_prt(mpt, "No PIO resource!\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
mpt_prt(mpt, "Downloading Firmware - Image Size %d\n",
|
||||
mpt->fw_image_size);
|
||||
|
||||
|
@ -608,7 +608,7 @@ struct mpt_softc {
|
||||
#endif
|
||||
uint32_t mpt_pers_mask;
|
||||
uint32_t
|
||||
: 8,
|
||||
: 7,
|
||||
unit : 8,
|
||||
ready : 1,
|
||||
fw_uploaded : 1,
|
||||
@ -625,7 +625,8 @@ struct mpt_softc {
|
||||
disabled : 1,
|
||||
is_spi : 1,
|
||||
is_sas : 1,
|
||||
is_fc : 1;
|
||||
is_fc : 1,
|
||||
is_1078 : 1;
|
||||
|
||||
u_int cfg_role;
|
||||
u_int role; /* role: none, ini, target, both */
|
||||
@ -982,12 +983,14 @@ mpt_read(struct mpt_softc *mpt, int offset)
|
||||
static __inline void
|
||||
mpt_pio_write(struct mpt_softc *mpt, size_t offset, uint32_t val)
|
||||
{
|
||||
KASSERT(mpt->pci_pio_reg != NULL, ("no PIO resource"));
|
||||
bus_space_write_4(mpt->pci_pio_st, mpt->pci_pio_sh, offset, val);
|
||||
}
|
||||
|
||||
static __inline uint32_t
|
||||
mpt_pio_read(struct mpt_softc *mpt, int offset)
|
||||
{
|
||||
KASSERT(mpt->pci_pio_reg != NULL, ("no PIO resource"));
|
||||
return (bus_space_read_4(mpt->pci_pio_st, mpt->pci_pio_sh, offset));
|
||||
}
|
||||
/*********************** Reply Frame/Request Management ***********************/
|
||||
|
@ -1279,8 +1279,9 @@ mpt_execute_req_a64(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
||||
char *mpt_off;
|
||||
union ccb *ccb;
|
||||
struct mpt_softc *mpt;
|
||||
int seg, first_lim;
|
||||
uint32_t flags, nxt_off;
|
||||
bus_addr_t chain_list_addr;
|
||||
int first_lim, seg, this_seg_lim;
|
||||
uint32_t addr, cur_off, flags, nxt_off, tf;
|
||||
void *sglp = NULL;
|
||||
MSG_REQUEST_HEADER *hdrp;
|
||||
SGE_SIMPLE64 *se;
|
||||
@ -1434,16 +1435,20 @@ bad:
|
||||
|
||||
se = (SGE_SIMPLE64 *) sglp;
|
||||
for (seg = 0; seg < first_lim; seg++, se++, dm_segs++) {
|
||||
uint32_t tf;
|
||||
|
||||
tf = flags;
|
||||
memset(se, 0, sizeof (*se));
|
||||
MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len);
|
||||
se->Address.Low = htole32(dm_segs->ds_addr & 0xffffffff);
|
||||
if (sizeof(bus_addr_t) > 4) {
|
||||
se->Address.High =
|
||||
htole32(((uint64_t)dm_segs->ds_addr) >> 32);
|
||||
addr = ((uint64_t)dm_segs->ds_addr) >> 32;
|
||||
/* SAS1078 36GB limitation WAR */
|
||||
if (mpt->is_1078 && (((uint64_t)dm_segs->ds_addr +
|
||||
MPI_SGE_LENGTH(se->FlagsLength)) >> 32) == 9) {
|
||||
addr |= (1 << 31);
|
||||
tf |= MPI_SGE_FLAGS_LOCAL_ADDRESS;
|
||||
}
|
||||
se->Address.High = htole32(addr);
|
||||
}
|
||||
MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len);
|
||||
tf = flags;
|
||||
if (seg == first_lim - 1) {
|
||||
tf |= MPI_SGE_FLAGS_LAST_ELEMENT;
|
||||
}
|
||||
@ -1468,15 +1473,11 @@ bad:
|
||||
|
||||
/*
|
||||
* Make up the rest of the data segments out of a chain element
|
||||
* (contiained in the current request frame) which points to
|
||||
* (contained in the current request frame) which points to
|
||||
* SIMPLE64 elements in the next request frame, possibly ending
|
||||
* with *another* chain element (if there's more).
|
||||
*/
|
||||
while (seg < nseg) {
|
||||
int this_seg_lim;
|
||||
uint32_t tf, cur_off;
|
||||
bus_addr_t chain_list_addr;
|
||||
|
||||
/*
|
||||
* Point to the chain descriptor. Note that the chain
|
||||
* descriptor is at the end of the *previous* list (whether
|
||||
@ -1504,7 +1505,7 @@ bad:
|
||||
nxt_off += MPT_RQSL(mpt);
|
||||
|
||||
/*
|
||||
* Now initialized the chain descriptor.
|
||||
* Now initialize the chain descriptor.
|
||||
*/
|
||||
memset(ce, 0, sizeof (*ce));
|
||||
|
||||
@ -1554,16 +1555,24 @@ bad:
|
||||
* set the end of list and end of buffer flags.
|
||||
*/
|
||||
while (seg < this_seg_lim) {
|
||||
tf = flags;
|
||||
memset(se, 0, sizeof (*se));
|
||||
MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len);
|
||||
se->Address.Low = htole32(dm_segs->ds_addr &
|
||||
0xffffffff);
|
||||
if (sizeof (bus_addr_t) > 4) {
|
||||
se->Address.High =
|
||||
htole32(((uint64_t)dm_segs->ds_addr) >> 32);
|
||||
addr = ((uint64_t)dm_segs->ds_addr) >> 32;
|
||||
/* SAS1078 36GB limitation WAR */
|
||||
if (mpt->is_1078 &&
|
||||
(((uint64_t)dm_segs->ds_addr +
|
||||
MPI_SGE_LENGTH(se->FlagsLength)) >>
|
||||
32) == 9) {
|
||||
addr |= (1 << 31);
|
||||
tf |= MPI_SGE_FLAGS_LOCAL_ADDRESS;
|
||||
}
|
||||
se->Address.High = htole32(addr);
|
||||
}
|
||||
MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len);
|
||||
tf = flags;
|
||||
if (seg == this_seg_lim - 1) {
|
||||
if (seg == this_seg_lim - 1) {
|
||||
tf |= MPI_SGE_FLAGS_LAST_ELEMENT;
|
||||
}
|
||||
if (seg == nseg - 1) {
|
||||
@ -1868,7 +1877,7 @@ bad:
|
||||
|
||||
/*
|
||||
* Make up the rest of the data segments out of a chain element
|
||||
* (contiained in the current request frame) which points to
|
||||
* (contained in the current request frame) which points to
|
||||
* SIMPLE32 elements in the next request frame, possibly ending
|
||||
* with *another* chain element (if there's more).
|
||||
*/
|
||||
@ -1904,7 +1913,7 @@ bad:
|
||||
nxt_off += MPT_RQSL(mpt);
|
||||
|
||||
/*
|
||||
* Now initialized the chain descriptor.
|
||||
* Now initialize the chain descriptor.
|
||||
*/
|
||||
memset(ce, 0, sizeof (*ce));
|
||||
|
||||
@ -1958,7 +1967,7 @@ bad:
|
||||
|
||||
MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len);
|
||||
tf = flags;
|
||||
if (seg == this_seg_lim - 1) {
|
||||
if (seg == this_seg_lim - 1) {
|
||||
tf |= MPI_SGE_FLAGS_LAST_ELEMENT;
|
||||
}
|
||||
if (seg == nseg - 1) {
|
||||
|
@ -438,6 +438,10 @@ mpt_pci_attach(device_t dev)
|
||||
case PCI_PRODUCT_LSI_FC7X04X:
|
||||
mpt->is_fc = 1;
|
||||
break;
|
||||
case PCI_PRODUCT_LSI_SAS1078:
|
||||
case PCI_PRODUCT_LSI_SAS1078DE:
|
||||
mpt->is_1078 = 1;
|
||||
/* FALLTHROUGH */
|
||||
case PCI_PRODUCT_LSI_SAS1064:
|
||||
case PCI_PRODUCT_LSI_SAS1064A:
|
||||
case PCI_PRODUCT_LSI_SAS1064E:
|
||||
@ -445,8 +449,6 @@ mpt_pci_attach(device_t dev)
|
||||
case PCI_PRODUCT_LSI_SAS1066E:
|
||||
case PCI_PRODUCT_LSI_SAS1068:
|
||||
case PCI_PRODUCT_LSI_SAS1068E:
|
||||
case PCI_PRODUCT_LSI_SAS1078:
|
||||
case PCI_PRODUCT_LSI_SAS1078DE:
|
||||
mpt->is_sas = 1;
|
||||
break;
|
||||
default:
|
||||
@ -527,23 +529,31 @@ mpt_pci_attach(device_t dev)
|
||||
mpt->pci_pio_reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
|
||||
&mpt_io_bar, RF_ACTIVE);
|
||||
if (mpt->pci_pio_reg == NULL) {
|
||||
device_printf(dev, "unable to map registers in PIO mode\n");
|
||||
goto bad;
|
||||
if (bootverbose) {
|
||||
device_printf(dev,
|
||||
"unable to map registers in PIO mode\n");
|
||||
}
|
||||
} else {
|
||||
mpt->pci_pio_st = rman_get_bustag(mpt->pci_pio_reg);
|
||||
mpt->pci_pio_sh = rman_get_bushandle(mpt->pci_pio_reg);
|
||||
}
|
||||
mpt->pci_pio_st = rman_get_bustag(mpt->pci_pio_reg);
|
||||
mpt->pci_pio_sh = rman_get_bushandle(mpt->pci_pio_reg);
|
||||
|
||||
/* Allocate kernel virtual memory for the 9x9's Mem0 region */
|
||||
mpt_mem_bar = PCIR_BAR(mpt_mem_bar);
|
||||
mpt->pci_reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
|
||||
&mpt_mem_bar, RF_ACTIVE);
|
||||
if (mpt->pci_reg == NULL) {
|
||||
device_printf(dev, "Unable to memory map registers.\n");
|
||||
if (mpt->is_sas) {
|
||||
if (bootverbose || mpt->is_sas || mpt->pci_pio_reg == NULL) {
|
||||
device_printf(dev,
|
||||
"Unable to memory map registers.\n");
|
||||
}
|
||||
if (mpt->is_sas || mpt->pci_pio_reg == NULL) {
|
||||
device_printf(dev, "Giving Up.\n");
|
||||
goto bad;
|
||||
}
|
||||
device_printf(dev, "Falling back to PIO mode.\n");
|
||||
if (bootverbose) {
|
||||
device_printf(dev, "Falling back to PIO mode.\n");
|
||||
}
|
||||
mpt->pci_st = mpt->pci_pio_st;
|
||||
mpt->pci_sh = mpt->pci_pio_sh;
|
||||
} else {
|
||||
|
@ -77,6 +77,7 @@
|
||||
#define MPT_OFFSET_REPLY_Q 0x44
|
||||
#define MPT_OFFSET_HOST_INDEX 0x50
|
||||
#define MPT_OFFSET_FUBAR 0x90
|
||||
#define MPT_OFFSET_RESET_1078 0x10fc
|
||||
|
||||
/* Bit Maps for DOORBELL register */
|
||||
enum DB_STATE_BITS {
|
||||
|
Loading…
x
Reference in New Issue
Block a user