Mercurial > illumos > illumos-gate
changeset 10663:4d59e1faf654
6881565 sata hba interfaces need to keep backward compatibility
author | Xiao-Yu Zhang <Xiao-Yu.Zhang@Sun.COM> |
---|---|
date | Mon, 28 Sep 2009 14:30:40 +0800 |
parents | fd0d1bbdb9a0 |
children | e29b5b8a591c |
files | usr/src/uts/common/io/sata/adapters/ahci/ahci.c usr/src/uts/common/io/sata/impl/sata.c usr/src/uts/common/sys/sata/impl/sata.h usr/src/uts/common/sys/sata/sata_hba.h |
diffstat | 4 files changed, 155 insertions(+), 122 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/io/sata/adapters/ahci/ahci.c Mon Sep 28 10:58:29 2009 +0800 +++ b/usr/src/uts/common/io/sata/adapters/ahci/ahci.c Mon Sep 28 14:30:40 2009 +0800 @@ -110,7 +110,7 @@ static int ahci_update_pmult_pscr(ahci_ctl_t *, ahci_addr_t *, sata_device_t *); static int ahci_update_pmult_gscr(ahci_ctl_t *, ahci_addr_t *, - sata_device_t *); + sata_pmult_gscr_t *); static int ahci_initialize_pmult(ahci_ctl_t *, ahci_port_t *, ahci_addr_t *, sata_device_t *); static int ahci_initialize_pmport(ahci_ctl_t *, ahci_port_t *, ahci_addr_t *); @@ -1087,7 +1087,7 @@ /* Allocate memory for the sata_hba_tran */ sata_hba_tran = kmem_zalloc(sizeof (sata_hba_tran_t), KM_SLEEP); - sata_hba_tran->sata_tran_hba_rev = SATA_TRAN_HBA_REV_3; + sata_hba_tran->sata_tran_hba_rev = SATA_TRAN_HBA_REV; sata_hba_tran->sata_tran_hba_dip = ahci_ctlp->ahcictl_dip; sata_hba_tran->sata_tran_hba_dma_attr = &ahci_ctlp->ahcictl_buffer_dma_attr; @@ -1254,7 +1254,7 @@ /* port mutliplier is removed. */ AHCIDBG(AHCIDBG_PMULT, ahci_ctlp, "ahci_tran_probe_port: " - "port-pmult is removed from port %s", portstr); + "pmult is removed from port %s", portstr); mutex_exit(&ahci_portp->ahciport_mutex); return (SATA_FAILURE); } @@ -1264,8 +1264,9 @@ * 1. A controller port. * A controller port should be ready here. * 2. A port multiplier. - * If it has not been initialized, initialized it. If it is - * initilaized, we need check the status of all its device ports. + * SATA_ADDR_PMULT_SPEC - if it is not initialized yet, initialize + * it and register the port multiplier to the framework. + * SATA_ADDR_PMULT - check the status of all its device ports. * 3. A port multiplier port. * If it has not been initialized, initialized it. * @@ -1273,29 +1274,22 @@ * initialization because we cannot do these time-consuming jobs in an * interrupt context. */ - if (AHCI_ADDR_IS_PORT(&addr)) { - if (ahci_portp->ahciport_device_type == SATA_DTYPE_PMULT) { - AHCI_ADDR_SET_PMULT(&pmult_addr, port); - port_state = ahci_portp->ahciport_port_state; - /* SATA Framework's first probe? */ - if (!(port_state & SATA_DSTATE_PMULT_INIT)) { - /* Initialize registers on a port multiplier */ - rval_init = ahci_initialize_pmult(ahci_ctlp, - ahci_portp, &pmult_addr, sd); - if (rval_init != AHCI_SUCCESS) { - AHCIDBG(AHCIDBG_PMULT, ahci_ctlp, - "ahci_tran_probe_port: " - "pmult initialization failed.", - NULL); - mutex_exit(&ahci_portp->ahciport_mutex); - return (SATA_FAILURE); - } - } - } - } else if (AHCI_ADDR_IS_PMULT(&addr)) { + if (sd->satadev_addr.qual & SATA_ADDR_PMULT_SPEC) { + AHCI_ADDR_SET_PMULT(&pmult_addr, port); + /* Initialize registers on a port multiplier */ + rval_init = ahci_initialize_pmult(ahci_ctlp, + ahci_portp, &pmult_addr, sd); + if (rval_init != AHCI_SUCCESS) { + AHCIDBG(AHCIDBG_PMULT, ahci_ctlp, + "ahci_tran_probe_port: " + "pmult initialization failed.", NULL); + mutex_exit(&ahci_portp->ahciport_mutex); + return (SATA_FAILURE); + } + } else if (sd->satadev_addr.qual & SATA_ADDR_PMULT) { /* Check pmports hotplug events */ (void) ahci_probe_pmult(ahci_ctlp, ahci_portp, &addr); - } else if (AHCI_ADDR_IS_PMPORT(&addr)) { + } else if (sd->satadev_addr.qual & SATA_ADDR_PMPORT) { if (ahci_probe_pmport(ahci_ctlp, ahci_portp, &addr, sd) != AHCI_SUCCESS) { rval = SATA_FAILURE; @@ -1393,19 +1387,8 @@ out: /* Register update only fails while probing a pmult/pmport */ - if (AHCI_ADDR_IS_PORT(&addr)) { + if (AHCI_ADDR_IS_PORT(&addr) || AHCI_ADDR_IS_PMULT(&addr)) { ahci_update_sata_registers(ahci_ctlp, port, sd); - if (ahci_portp->ahciport_device_type == SATA_DTYPE_PMULT) - if (port_state & SATA_STATE_READY) - if (ahci_update_pmult_gscr(ahci_ctlp, - &pmult_addr, sd) != AHCI_SUCCESS) - rval = SATA_FAILURE; - } else if (AHCI_ADDR_IS_PMULT(&addr)) { - ahci_update_sata_registers(ahci_ctlp, port, sd); - if (port_state & SATA_STATE_READY) - if (ahci_update_pmult_gscr(ahci_ctlp, - &addr, sd) != AHCI_SUCCESS) - rval = SATA_FAILURE; } else if (AHCI_ADDR_IS_PMPORT(&addr)) { if (port_state & SATA_STATE_READY) if (ahci_update_pmult_pscr(ahci_ctlp, @@ -1451,8 +1434,7 @@ { ahci_ctl_t *ahci_ctlp; ahci_port_t *ahci_portp; - ahci_addr_t addr, addr_pmult; - sata_device_t sdevice; + ahci_addr_t addr; uint8_t cport = spkt->satapkt_device.satadev_addr.cport; uint8_t port; char portstr[10]; @@ -1487,28 +1469,6 @@ return (SATA_TRAN_PORT_ERROR); } - /* Port multiplier and pmport are correctly initialized? */ - if (!(ahci_portp->ahciport_port_state & - SATA_DSTATE_PMULT_INIT)) { - AHCI_ADDR_SET_PMULT(&addr_pmult, port); - if (!ddi_in_panic() || - ahci_initialize_pmult(ahci_ctlp, ahci_portp, - &addr_pmult, &sdevice) != AHCI_SUCCESS) { - spkt->satapkt_reason = SATA_PKT_PORT_ERROR; - spkt->satapkt_device.satadev_type = - AHCIPORT_GET_DEV_TYPE(ahci_portp, &addr); - spkt->satapkt_device.satadev_state = - AHCIPORT_GET_STATE(ahci_portp, &addr); - ahci_update_sata_registers(ahci_ctlp, port, - &spkt->satapkt_device); - AHCIDBG(AHCIDBG_ERRS, ahci_ctlp, - "ahci_tran_start returning PORT_ERROR " - "while pmult is not initialized " - "at port %d", port); - mutex_exit(&ahci_portp->ahciport_mutex); - return (SATA_TRAN_PORT_ERROR); - } - } if (!(AHCIPORT_GET_STATE(ahci_portp, &addr) & SATA_STATE_READY)) { if (!ddi_in_panic() || @@ -4107,12 +4067,12 @@ */ static int ahci_update_pmult_gscr(ahci_ctl_t *ahci_ctlp, ahci_addr_t *addrp, - sata_device_t *sd) + sata_pmult_gscr_t *sg) { - READ_PMULT(addrp, SATA_PMULT_GSCR0, &sd->satadev_gscr.gscr0, err); - READ_PMULT(addrp, SATA_PMULT_GSCR1, &sd->satadev_gscr.gscr1, err); - READ_PMULT(addrp, SATA_PMULT_GSCR2, &sd->satadev_gscr.gscr2, err); - READ_PMULT(addrp, SATA_PMULT_GSCR64, &sd->satadev_gscr.gscr64, err); + READ_PMULT(addrp, SATA_PMULT_GSCR0, &sg->gscr0, err); + READ_PMULT(addrp, SATA_PMULT_GSCR1, &sg->gscr1, err); + READ_PMULT(addrp, SATA_PMULT_GSCR2, &sg->gscr2, err); + READ_PMULT(addrp, SATA_PMULT_GSCR64, &sg->gscr64, err); return (AHCI_SUCCESS); @@ -4151,6 +4111,7 @@ ahci_initialize_pmult(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp, ahci_addr_t *addrp, sata_device_t *sd) { + sata_pmult_gscr_t sg; uint32_t gscr64; uint8_t port = addrp->aa_port; @@ -4193,16 +4154,16 @@ /* * Fetch the number of device ports of the port multiplier */ - if (ahci_update_pmult_gscr(ahci_ctlp, addrp, sd) != AHCI_SUCCESS) + if (ahci_update_pmult_gscr(ahci_ctlp, addrp, &sg) != AHCI_SUCCESS) return (AHCI_FAILURE); - /* If it's not in the blacklist, use the value in GSCR2 */ - if (sata_check_pmult_blacklist(sd) == SATA_FAILURE) - sd->satadev_add_info = sd->satadev_gscr.gscr2 & - SATA_PMULT_PORTNUM_MASK; + /* Register the port multiplier to SATA Framework. */ + mutex_exit(&ahci_portp->ahciport_mutex); + sata_register_pmult(ahci_ctlp->ahcictl_dip, sd, &sg); + mutex_enter(&ahci_portp->ahciport_mutex); ahci_portp->ahciport_pmult_info->ahcipmi_num_dev_ports = - sd->satadev_add_info; + sd->satadev_add_info & SATA_PMULT_PORTNUM_MASK; AHCIDBG(AHCIDBG_INFO|AHCIDBG_PMULT, ahci_ctlp, "port %d: pmult sub-port number updated to %x.", port, @@ -9695,6 +9656,7 @@ ahci_addrp->aa_qual = AHCI_ADDR_PORT; break; case SATA_ADDR_PMULT: + case SATA_ADDR_PMULT_SPEC: ahci_addrp->aa_qual = AHCI_ADDR_PMULT; break; case SATA_ADDR_DPMPORT:
--- a/usr/src/uts/common/io/sata/impl/sata.c Mon Sep 28 10:58:29 2009 +0800 +++ b/usr/src/uts/common/io/sata/impl/sata.c Mon Sep 28 14:30:40 2009 +0800 @@ -131,7 +131,7 @@ #define LEGACY_HWID_LEN 64 /* Model (40) + Serial (20) + pad */ -static char sata_rev_tag[] = {"1.45"}; +static char sata_rev_tag[] = {"1.46"}; /* * SATA cb_ops functions @@ -264,7 +264,7 @@ static int sata_reprobe_port(sata_hba_inst_t *, sata_device_t *, int); static int sata_reprobe_pmult(sata_hba_inst_t *, sata_device_t *, int); static int sata_reprobe_pmport(sata_hba_inst_t *, sata_device_t *, int); -static void sata_alloc_pmult(sata_hba_inst_t *, sata_device_t *); +static int sata_alloc_pmult(sata_hba_inst_t *, sata_device_t *); static void sata_free_pmult(sata_hba_inst_t *, sata_device_t *); static int sata_add_device(dev_info_t *, sata_hba_inst_t *, sata_device_t *); static int sata_offline_device(sata_hba_inst_t *, sata_device_t *, @@ -1856,30 +1856,61 @@ } /* - * Search a port multiplier in the blacklist and update the flags if a match - * is found. - * - * Returns: - * SATA_SUCCESS if any matched entry is found. - * SATA_FAILURE if no matched entry is found. - */ -int -sata_check_pmult_blacklist(sata_device_t *sd) -{ + * Register a port multiplier to framework. + * 1) Store the GSCR values in the previous allocated pmult_info strctures. + * 2) Search in the blacklist and update the number of the device ports of the + * port multiplier. + * + * Void return. + */ +void +sata_register_pmult(dev_info_t *dip, sata_device_t *sd, sata_pmult_gscr_t *sg) +{ + sata_hba_inst_t *sata_hba_inst = NULL; + sata_pmult_info_t *pmultinfo; sata_pmult_bl_t *blp; + int cport = sd->satadev_addr.cport; + + mutex_enter(&sata_mutex); + for (sata_hba_inst = sata_hba_list; sata_hba_inst != NULL; + sata_hba_inst = sata_hba_inst->satahba_next) { + if (SATA_DIP(sata_hba_inst) == dip) + if (sata_hba_inst->satahba_attached == 1) + break; + } + mutex_exit(&sata_mutex); + /* HBA not attached? */ + if (sata_hba_inst == NULL) + return; + + /* Number of pmports */ + sd->satadev_add_info = sg->gscr2 & SATA_PMULT_PORTNUM_MASK; + + /* Check the blacklist */ for (blp = sata_pmult_blacklist; blp->bl_gscr0; blp++) { - if (sd->satadev_gscr.gscr0 != blp->bl_gscr0 && blp->bl_gscr0) + if (sg->gscr0 != blp->bl_gscr0 && blp->bl_gscr0) continue; - if (sd->satadev_gscr.gscr1 != blp->bl_gscr1 && blp->bl_gscr1) + if (sg->gscr1 != blp->bl_gscr1 && blp->bl_gscr1) continue; - if (sd->satadev_gscr.gscr2 != blp->bl_gscr2 && blp->bl_gscr2) + if (sg->gscr2 != blp->bl_gscr2 && blp->bl_gscr2) continue; cmn_err(CE_WARN, "!Port multiplier is on the blacklist."); sd->satadev_add_info = blp->bl_flags; - return (SATA_SUCCESS); - } - return (SATA_FAILURE); + break; + } + + /* Register the port multiplier GSCR */ + mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst, cport))); + pmultinfo = SATA_PMULT_INFO(sata_hba_inst, cport); + if (pmultinfo != NULL) { + pmultinfo->pmult_gscr = *sg; + pmultinfo->pmult_num_dev_ports = + sd->satadev_add_info & SATA_PMULT_PORTNUM_MASK; + SATADBG1(SATA_DBG_PMULT, sata_hba_inst, + "Port multiplier registered at port %d", cport); + } + mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst, cport))); } /* @@ -9223,7 +9254,9 @@ mutex_exit(&cportinfo->cport_mutex); /* Allocate sata_pmult_info and sata_pmport_info */ - sata_alloc_pmult(sata_hba_inst, &sata_device); + if (sata_alloc_pmult(sata_hba_inst, &sata_device) != + SATA_SUCCESS) + continue; /* Log the information of the port multiplier */ sata_show_pmult_info(sata_hba_inst, &sata_device); @@ -10041,7 +10074,9 @@ cportinfo->cport_addr.cport); mutex_exit(&cportinfo->cport_mutex); - sata_alloc_pmult(sata_hba_inst, sata_device); + if (sata_alloc_pmult(sata_hba_inst, sata_device) != + SATA_SUCCESS) + return (SATA_FAILURE); sata_show_pmult_info(sata_hba_inst, sata_device); mutex_enter(&cportinfo->cport_mutex); @@ -10236,21 +10271,17 @@ * registers, so it is still necessary to update the information of * all drives attached to the previous port multiplier afterwards. */ - if ((sata_device->satadev_gscr.gscr0 != pmultinfo->pmult_gscr.gscr0) || - (sata_device->satadev_gscr.gscr1 != pmultinfo->pmult_gscr.gscr1) || - (sata_device->satadev_gscr.gscr2 != pmultinfo->pmult_gscr.gscr2)) { - - /* Device changed: PMult -> another PMult */ - mutex_exit(&cportinfo->cport_mutex); - sata_free_pmult(sata_hba_inst, sata_device); - sata_alloc_pmult(sata_hba_inst, sata_device); - mutex_enter(&cportinfo->cport_mutex); - - SATADBG1(SATA_DBG_PMULT, sata_hba_inst, - "SATA port multiplier [changed] at port %d", cport); - sata_log(sata_hba_inst, CE_WARN, - "SATA port multiplier detected at port %d", cport); - } + /* Device changed: PMult -> another PMult */ + mutex_exit(&cportinfo->cport_mutex); + sata_free_pmult(sata_hba_inst, sata_device); + if (sata_alloc_pmult(sata_hba_inst, sata_device) != SATA_SUCCESS) + return (SATA_FAILURE); + mutex_enter(&cportinfo->cport_mutex); + + SATADBG1(SATA_DBG_PMULT, sata_hba_inst, + "SATA port multiplier [changed] at port %d", cport); + sata_log(sata_hba_inst, CE_WARN, + "SATA port multiplier detected at port %d", cport); /* * Mark all the port multiplier port behind the port @@ -10571,16 +10602,18 @@ * * NOTE: No Mutex should be hold. */ -static void +static int sata_alloc_pmult(sata_hba_inst_t *sata_hba_inst, sata_device_t *sata_device) { dev_info_t *dip = SATA_DIP(sata_hba_inst); sata_cport_info_t *cportinfo = NULL; sata_pmult_info_t *pmultinfo = NULL; sata_pmport_info_t *pmportinfo = NULL; + sata_device_t sd; dev_t minor_number; char name[16]; uint8_t cport = sata_device->satadev_addr.cport; + int rval; int npmport; cportinfo = SATA_CPORT_INFO(sata_hba_inst, cport); @@ -10600,8 +10633,34 @@ pmultinfo->pmult_addr = sata_device->satadev_addr; pmultinfo->pmult_addr.qual = SATA_ADDR_PMULT; pmultinfo->pmult_state = SATA_STATE_PROBING; - pmultinfo->pmult_gscr = sata_device->satadev_gscr; - pmultinfo->pmult_num_dev_ports = sata_device->satadev_add_info; + + /* + * Probe the port multiplier with qualifier SATA_ADDR_PMULT_SPEC, + * The HBA driver should initialize and register the port multiplier, + * sata_register_pmult() will fill following fields, + * + sata_pmult_info.pmult_gscr + * + sata_pmult_info.pmult_num_dev_ports + */ + sd.satadev_addr = sata_device->satadev_addr; + sd.satadev_addr.qual = SATA_ADDR_PMULT_SPEC; + mutex_exit(&cportinfo->cport_mutex); + rval = (*SATA_PROBE_PORT_FUNC(sata_hba_inst)) + (SATA_DIP(sata_hba_inst), &sd); + mutex_enter(&cportinfo->cport_mutex); + + if (rval != SATA_SUCCESS || + (sd.satadev_type != SATA_DTYPE_PMULT) || + !(sd.satadev_state & SATA_DSTATE_PMULT_INIT)) { + SATA_CPORTINFO_PMULT_INFO(cportinfo) = NULL; + kmem_free(pmultinfo, sizeof (sata_pmult_info_t)); + cportinfo->cport_state = SATA_PSTATE_FAILED; + cportinfo->cport_dev_type = SATA_DTYPE_UNKNOWN; + mutex_exit(&cportinfo->cport_mutex); + SATADBG1(SATA_DBG_PMULT, sata_hba_inst, + "sata_alloc_pmult: failed to initialize pmult " + "at port %d.", cport) + return (SATA_FAILURE); + } /* Initialize pmport_info structure */ for (npmport = 0; npmport < pmultinfo->pmult_num_dev_ports; @@ -10642,6 +10701,7 @@ pmultinfo->pmult_state |= (SATA_STATE_PROBED|SATA_STATE_READY); mutex_exit(&cportinfo->cport_mutex); + return (SATA_SUCCESS); } /* @@ -11544,6 +11604,7 @@ /* * Log/display port multiplier information + * No Mutex should be hold. */ static void sata_show_pmult_info(sata_hba_inst_t *sata_hba_inst, @@ -11551,13 +11612,21 @@ { _NOTE(ARGUNUSED(sata_hba_inst)) + int cport = sata_device->satadev_addr.cport; + sata_pmult_info_t *pmultinfo; char msg_buf[MAXPATHLEN]; uint32_t gscr0, gscr1, gscr2, gscr64; - gscr0 = sata_device->satadev_gscr.gscr0; - gscr1 = sata_device->satadev_gscr.gscr1; - gscr2 = sata_device->satadev_gscr.gscr2; - gscr64 = sata_device->satadev_gscr.gscr64; + mutex_enter(&SATA_CPORT_MUTEX(sata_hba_inst, cport)); + pmultinfo = SATA_PMULT_INFO(sata_hba_inst, cport); + if (pmultinfo == NULL) + return; + + gscr0 = pmultinfo->pmult_gscr.gscr0; + gscr1 = pmultinfo->pmult_gscr.gscr1; + gscr2 = pmultinfo->pmult_gscr.gscr2; + gscr64 = pmultinfo->pmult_gscr.gscr64; + mutex_exit(&SATA_CPORT_MUTEX(sata_hba_inst, cport)); cmn_err(CE_CONT, "?Port Multiplier %d device-ports found at port %d", sata_device->satadev_add_info, sata_device->satadev_addr.cport); @@ -18522,8 +18591,12 @@ if (SATA_CPORTINFO_PMULT_INFO(cportinfo) != NULL) { /* Log the info of new port multiplier */ + mutex_exit(&SATA_CPORT_INFO(sata_hba_inst, + saddr->cport)->cport_mutex); sata_show_pmult_info(sata_hba_inst, &sata_device); + mutex_enter(&SATA_CPORT_INFO(sata_hba_inst, + saddr->cport)->cport_mutex); } ASSERT(SATA_CPORTINFO_PMULT_INFO(cportinfo) != NULL);
--- a/usr/src/uts/common/sys/sata/impl/sata.h Mon Sep 28 10:58:29 2009 +0800 +++ b/usr/src/uts/common/sys/sata/impl/sata.h Mon Sep 28 14:30:40 2009 +0800 @@ -835,7 +835,7 @@ #endif -/* sata_rev_tag 1.45 */ +/* sata_rev_tag 1.46 */ #ifdef __cplusplus }
--- a/usr/src/uts/common/sys/sata/sata_hba.h Mon Sep 28 10:58:29 2009 +0800 +++ b/usr/src/uts/common/sys/sata/sata_hba.h Mon Sep 28 14:30:40 2009 +0800 @@ -83,6 +83,7 @@ #define SATA_ADDR_PMPORT 0x08 /* Port Multiplier's device port */ #define SATA_ADDR_CNTRL 0x10 /* Controller */ #define SATA_ADDR_PMULT 0x20 /* Port Multiplier */ +#define SATA_ADDR_PMULT_SPEC 0x40 /* Port Multiplier Specific */ /* * SATA port status and control register block. @@ -114,6 +115,7 @@ uint32_t gscr1; /* Resrved Information register */ uint32_t gscr2; /* Port Information register */ uint32_t gscr64; /* Feature register */ + uint32_t resv[4]; /* Reseved */ }; typedef struct sata_pmult_gscr sata_pmult_gscr_t; @@ -136,8 +138,7 @@ * a value specific for a reported event. */ #define SATA_DEVICE_REV_1 1 -#define SATA_DEVICE_REV_2 2 -#define SATA_DEVICE_REV SATA_DEVICE_REV_2 +#define SATA_DEVICE_REV SATA_DEVICE_REV_1 struct sata_device { @@ -146,9 +147,6 @@ uint32_t satadev_state; /* Port or device state */ uint32_t satadev_type; /* Attached device type */ struct sata_port_scr satadev_scr; /* Port status and ctrl regs */ - struct sata_pmult_gscr satadev_gscr; /* Port multiplier specific */ - /* global status and control */ - /* registers */ uint32_t satadev_add_info; /* additional information, */ /* function specific */ }; @@ -746,7 +744,7 @@ sata_pkt_t *sata_get_rdwr_pmult_pkt(dev_info_t *, sata_device_t *, uint8_t, uint32_t, uint32_t); void sata_free_rdwr_pmult_pkt(sata_pkt_t *); -int sata_check_pmult_blacklist(sata_device_t *); +void sata_register_pmult(dev_info_t *, sata_device_t *, sata_pmult_gscr_t *); void sata_free_dma_resources(sata_pkt_t *); /*