Use information about max data size that the controller is able to operate

Using DFLTPHYS/MAXPHYS is not always OK, instead make it possible for the
controller driver to provide maximum data size to MMCCAM, and use it there.

The old stack already does this.

Reviewed by:	manu
Approved by:	imp (mentor)
Differential Revision:	https://reviews.freebsd.org/D15892
This commit is contained in:
Ilya Bakulin 2019-04-01 18:49:39 +00:00
parent e9e2022e74
commit 5d20e65174
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=345775
4 changed files with 41 additions and 7 deletions

View File

@ -256,6 +256,8 @@ aw_mmc_cam_action(struct cam_sim *sim, union ccb *ccb)
cts->proto_specific.mmc.host_f_min = sc->aw_host.f_min;
cts->proto_specific.mmc.host_f_max = sc->aw_host.f_max;
cts->proto_specific.mmc.host_caps = sc->aw_host.caps;
cts->proto_specific.mmc.host_max_data = (sc->aw_mmc_conf->dma_xferlen *
AW_MMC_DMA_SEGS) / MMC_SECTOR_SIZE;
memcpy(&cts->proto_specific.mmc.ios, &sc->aw_host.ios, sizeof(struct mmc_ios));
ccb->ccb_h.status = CAM_REQ_CMP;
break;

View File

@ -1051,6 +1051,7 @@ struct ccb_trans_settings_mmc {
#define MMC_CAP_8_BIT_DATA (1 << 1) /* Can do 8-bit data transfers */
#define MMC_CAP_HSPEED (1 << 2) /* Can do High Speed transfers */
uint32_t host_caps;
uint32_t host_max_data;
};
/* Get/Set transfer rate/width/disconnection/tag queueing settings */

View File

@ -1195,6 +1195,27 @@ sdda_get_host_caps(struct cam_periph *periph, union ccb *ccb)
return (cts->host_caps);
}
static uint32_t
sdda_get_max_data(struct cam_periph *periph, union ccb *ccb)
{
struct ccb_trans_settings_mmc *cts;
cts = &ccb->cts.proto_specific.mmc;
memset(cts, 0, sizeof(struct ccb_trans_settings_mmc));
ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
ccb->ccb_h.flags = CAM_DIR_NONE;
ccb->ccb_h.retry_count = 0;
ccb->ccb_h.timeout = 100;
ccb->ccb_h.cbfcnp = NULL;
xpt_action(ccb);
if (ccb->ccb_h.status != CAM_REQ_CMP)
panic("Cannot get host max data");
KASSERT(cts->host_max_data != 0, ("host_max_data == 0?!"));
return (cts->host_max_data);
}
static void
sdda_start_init(void *context, union ccb *start_ccb)
{
@ -1420,7 +1441,6 @@ sdda_add_part(struct cam_periph *periph, u_int type, const char *name,
struct sdda_softc *sc = (struct sdda_softc *)periph->softc;
struct sdda_part *part;
struct ccb_pathinq cpi;
u_int maxio;
CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH,
("Partition type '%s', size %ju %s\n",
@ -1479,12 +1499,9 @@ sdda_add_part(struct cam_periph *periph, u_int type, const char *name,
part->disk->d_gone = sddadiskgonecb;
part->disk->d_name = part->name;
part->disk->d_drv1 = part;
maxio = cpi.maxio; /* Honor max I/O size of SIM */
if (maxio == 0)
maxio = DFLTPHYS; /* traditional default */
else if (maxio > MAXPHYS)
maxio = MAXPHYS; /* for safety */
part->disk->d_maxsize = maxio;
part->disk->d_maxsize =
MIN(MAXPHYS, sdda_get_max_data(periph,
(union ccb *)&cpi) * mmc_get_sector_size(periph));
part->disk->d_unit = cnt;
part->disk->d_flags = 0;
strlcpy(part->disk->d_descr, sc->card_id_string,

View File

@ -2580,6 +2580,7 @@ sdhci_cam_action(struct cam_sim *sim, union ccb *ccb)
case XPT_GET_TRAN_SETTINGS:
{
struct ccb_trans_settings *cts = &ccb->cts;
uint32_t max_data;
if (sdhci_debug > 1)
slot_printf(slot, "Got XPT_GET_TRAN_SETTINGS\n");
@ -2593,6 +2594,19 @@ sdhci_cam_action(struct cam_sim *sim, union ccb *ccb)
cts->proto_specific.mmc.host_f_min = slot->host.f_min;
cts->proto_specific.mmc.host_f_max = slot->host.f_max;
cts->proto_specific.mmc.host_caps = slot->host.caps;
/*
* Re-tuning modes 1 and 2 restrict the maximum data length
* per read/write command to 4 MiB.
*/
if (slot->opt & SDHCI_TUNING_ENABLED &&
(slot->retune_mode == SDHCI_RETUNE_MODE_1 ||
slot->retune_mode == SDHCI_RETUNE_MODE_2)) {
max_data = 4 * 1024 * 1024 / MMC_SECTOR_SIZE;
} else {
max_data = 65535;
}
cts->proto_specific.mmc.host_max_data = max_data;
memcpy(&cts->proto_specific.mmc.ios, &slot->host.ios, sizeof(struct mmc_ios));
ccb->ccb_h.status = CAM_REQ_CMP;
break;