summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/dev/mmc/mmcsd.c
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-08-07 14:56:50 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-09-21 10:29:37 +0200
commitc37f9fba70085fedc8eede7559489d2321393005 (patch)
tree042455ebf1fa89a277a825f72e1ed805d0b4d296 /freebsd/sys/dev/mmc/mmcsd.c
parentUpdate to FreeBSD head 2017-06-01 (diff)
downloadrtems-libbsd-c37f9fba70085fedc8eede7559489d2321393005.tar.bz2
Update to FreeBSD head 2017-08-01
Git mirror commit f5002f5e5f78cae9f0269d812dc0aedb0339312c. Update #3472.
Diffstat (limited to '')
-rw-r--r--freebsd/sys/dev/mmc/mmcsd.c298
1 files changed, 208 insertions, 90 deletions
diff --git a/freebsd/sys/dev/mmc/mmcsd.c b/freebsd/sys/dev/mmc/mmcsd.c
index 5066e250..195feae2 100644
--- a/freebsd/sys/dev/mmc/mmcsd.c
+++ b/freebsd/sys/dev/mmc/mmcsd.c
@@ -108,7 +108,8 @@ __FBSDID("$FreeBSD$");
struct mmcsd_softc;
struct mmcsd_part {
- struct mtx part_mtx;
+ struct mtx disk_mtx;
+ struct mtx ioctl_mtx;
struct mmcsd_softc *sc;
#ifndef __rtems__
struct disk *disk;
@@ -120,6 +121,7 @@ struct mmcsd_part {
u_int type;
int running;
int suspend;
+ int ioctl;
bool ro;
char name[MMCSD_PART_NAMELEN];
};
@@ -129,6 +131,9 @@ struct mmcsd_softc {
device_t mmcbr;
struct mmcsd_part *part[MMC_PART_MAX];
enum mmc_card_mode mode;
+ u_int max_data; /* Maximum data size [blocks] */
+ u_int erase_sector; /* Device native erase sector size [blocks] */
+ uint8_t high_cap; /* High Capacity device (block addressed) */
uint8_t part_curr; /* Partition currently switched to */
uint8_t ext_csd[MMC_EXTCSD_SIZE];
uint16_t rca;
@@ -199,15 +204,25 @@ static int mmcsd_slicer(device_t dev, const char *provider,
static int mmcsd_switch_part(device_t bus, device_t dev, uint16_t rca,
u_int part);
-#define MMCSD_PART_LOCK(_part) mtx_lock(&(_part)->part_mtx)
-#define MMCSD_PART_UNLOCK(_part) mtx_unlock(&(_part)->part_mtx)
-#define MMCSD_PART_LOCK_INIT(_part) \
- mtx_init(&(_part)->part_mtx, (_part)->name, "mmcsd part", MTX_DEF)
-#define MMCSD_PART_LOCK_DESTROY(_part) mtx_destroy(&(_part)->part_mtx);
-#define MMCSD_PART_ASSERT_LOCKED(_part) \
- mtx_assert(&(_part)->part_mtx, MA_OWNED);
-#define MMCSD_PART_ASSERT_UNLOCKED(_part) \
- mtx_assert(&(_part)->part_mtx, MA_NOTOWNED);
+#define MMCSD_DISK_LOCK(_part) mtx_lock(&(_part)->disk_mtx)
+#define MMCSD_DISK_UNLOCK(_part) mtx_unlock(&(_part)->disk_mtx)
+#define MMCSD_DISK_LOCK_INIT(_part) \
+ mtx_init(&(_part)->disk_mtx, (_part)->name, "mmcsd disk", MTX_DEF)
+#define MMCSD_DISK_LOCK_DESTROY(_part) mtx_destroy(&(_part)->disk_mtx);
+#define MMCSD_DISK_ASSERT_LOCKED(_part) \
+ mtx_assert(&(_part)->disk_mtx, MA_OWNED);
+#define MMCSD_DISK_ASSERT_UNLOCKED(_part) \
+ mtx_assert(&(_part)->disk_mtx, MA_NOTOWNED);
+
+#define MMCSD_IOCTL_LOCK(_part) mtx_lock(&(_part)->ioctl_mtx)
+#define MMCSD_IOCTL_UNLOCK(_part) mtx_unlock(&(_part)->ioctl_mtx)
+#define MMCSD_IOCTL_LOCK_INIT(_part) \
+ mtx_init(&(_part)->ioctl_mtx, (_part)->name, "mmcsd IOCTL", MTX_DEF)
+#define MMCSD_IOCTL_LOCK_DESTROY(_part) mtx_destroy(&(_part)->ioctl_mtx);
+#define MMCSD_IOCTL_ASSERT_LOCKED(_part) \
+ mtx_assert(&(_part)->ioctl_mtx, MA_OWNED);
+#define MMCSD_IOCLT_ASSERT_UNLOCKED(_part) \
+ mtx_assert(&(_part)->ioctl_mtx, MA_NOTOWNED);
static int
mmcsd_probe(device_t dev)
@@ -277,7 +292,7 @@ rtems_bsd_mmcsd_disk_read_write(struct mmcsd_part *part, rtems_blkdev_request *b
data_flags = MMC_DATA_READ;
}
- MMCSD_PART_LOCK(part);
+ MMCSD_DISK_LOCK(part);
for (i = 0; i < buffer_count; ++i) {
rtems_blkdev_sg_buffer *sg = &blkreq->bufs [i];
@@ -354,7 +369,7 @@ rtems_bsd_mmcsd_disk_read_write(struct mmcsd_part *part, rtems_blkdev_request *b
error:
- MMCSD_PART_UNLOCK(part);
+ MMCSD_DISK_UNLOCK(part);
rtems_blkdev_request_done(blkreq, status_code);
@@ -439,6 +454,18 @@ mmcsd_attach(device_t dev)
sc->dev = dev;
sc->mmcbr = mmcbr = device_get_parent(dev);
sc->mode = mmcbr_get_mode(mmcbr);
+ /*
+ * Note that in principle with an SDHCI-like re-tuning implementation,
+ * the maximum data size can change at runtime due to a device removal/
+ * insertion that results in switches to/from a transfer mode involving
+ * re-tuning, iff there are multiple devices on a given bus. Until now
+ * mmc(4) lacks support for rescanning already attached buses, however,
+ * and sdhci(4) to date has no support for shared buses in the first
+ * place either.
+ */
+ sc->max_data = mmc_get_max_data(dev);
+ sc->erase_sector = mmc_get_erase_sector(dev);
+ sc->high_cap = mmc_get_high_cap(dev);
sc->rca = mmc_get_rca(dev);
/* Only MMC >= 4.x devices support EXT_CSD. */
@@ -492,7 +519,7 @@ mmcsd_attach(device_t dev)
(ext_csd[EXT_CSD_ENH_START_ADDR + 1] << 8) +
(ext_csd[EXT_CSD_ENH_START_ADDR + 2] << 16) +
(ext_csd[EXT_CSD_ENH_START_ADDR + 3] << 24)) *
- (mmc_get_high_cap(dev) ? MMC_SECTOR_SIZE : 1);
+ (sc->high_cap != 0 ? MMC_SECTOR_SIZE : 1);
} else if (bootverbose)
device_printf(dev,
"enhanced user data area spans entire device\n");
@@ -505,7 +532,7 @@ mmcsd_attach(device_t dev)
ro = mmc_get_read_only(dev);
mmcsd_add_part(sc, EXT_CSD_PART_CONFIG_ACC_DEFAULT, "mmcsd",
device_get_unit(dev), mmc_get_media_size(dev) * sector_size,
- mmc_get_erase_sector(dev) * sector_size, ro);
+ sc->erase_sector * sector_size, ro);
if (mmc_get_spec_vers(dev) < 3)
return (0);
@@ -644,7 +671,16 @@ mmcsd_add_part(struct mmcsd_softc *sc, u_int type, const char *name, u_int cnt,
part->ro = ro;
snprintf(part->name, sizeof(part->name), name, device_get_unit(dev));
- /* For the RPMB partition, allow IOCTL access only. */
+ MMCSD_IOCTL_LOCK_INIT(part);
+
+ /*
+ * For the RPMB partition, allow IOCTL access only.
+ * NB: If ever attaching RPMB partitions to disk(9), the re-tuning
+ * implementation and especially its pausing need to be revisited,
+ * because then re-tuning requests may be issued by the IOCTL half
+ * of this driver while re-tuning is already paused by the disk(9)
+ * one and vice versa.
+ */
if (type == EXT_CSD_PART_CONFIG_ACC_RPMB) {
make_dev_args_init(&args);
args.mda_flags = MAKEDEV_CHECKNAME | MAKEDEV_WAITOK;
@@ -659,7 +695,7 @@ mmcsd_add_part(struct mmcsd_softc *sc, u_int type, const char *name, u_int cnt,
return;
}
} else {
- MMCSD_PART_LOCK_INIT(part);
+ MMCSD_DISK_LOCK_INIT(part);
#ifndef __rtems__
d = part->disk = disk_alloc();
@@ -672,7 +708,7 @@ mmcsd_add_part(struct mmcsd_softc *sc, u_int type, const char *name, u_int cnt,
d->d_name = part->name;
d->d_drv1 = part;
d->d_sectorsize = mmc_get_sector_size(dev);
- d->d_maxsize = mmc_get_max_data(dev) * d->d_sectorsize;
+ d->d_maxsize = sc->max_data * d->d_sectorsize;
d->d_mediasize = media_size;
d->d_stripesize = erase_size;
d->d_unit = cnt;
@@ -704,7 +740,7 @@ mmcsd_add_part(struct mmcsd_softc *sc, u_int type, const char *name, u_int cnt,
part->name, cnt, bytes, unit, mmc_get_card_id_string(dev),
ro ? " (read-only)" : "", device_get_nameunit(mmcbr),
speed / 1000000, (speed / 100000) % 10,
- mmcsd_bus_bit_width(dev), mmc_get_max_data(dev));
+ mmcsd_bus_bit_width(dev), sc->max_data);
} else if (type == EXT_CSD_PART_CONFIG_ACC_RPMB) {
printf("%s: %ju%sB partion %d%s at %s\n", part->name, bytes,
unit, type, ro ? " (read-only)" : "",
@@ -795,19 +831,27 @@ mmcsd_detach(device_t dev)
for (i = 0; i < MMC_PART_MAX; i++) {
part = sc->part[i];
- if (part != NULL && part->disk != NULL) {
- MMCSD_PART_LOCK(part);
- part->suspend = 0;
- if (part->running > 0) {
- /* kill thread */
- part->running = 0;
- wakeup(part);
- /* wait for thread to finish. */
- while (part->running != -1)
- msleep(part, &part->part_mtx, 0,
- "detach", 0);
+ if (part != NULL) {
+ if (part->disk != NULL) {
+ MMCSD_DISK_LOCK(part);
+ part->suspend = 0;
+ if (part->running > 0) {
+ /* kill thread */
+ part->running = 0;
+ wakeup(part);
+ /* wait for thread to finish. */
+ while (part->running != -1)
+ msleep(part, &part->disk_mtx, 0,
+ "mmcsd disk detach", 0);
+ }
+ MMCSD_DISK_UNLOCK(part);
}
- MMCSD_PART_UNLOCK(part);
+ MMCSD_IOCTL_LOCK(part);
+ while (part->ioctl > 0)
+ msleep(part, &part->ioctl_mtx, 0,
+ "mmcsd IOCTL detach", 0);
+ part->ioctl = -1;
+ MMCSD_IOCTL_UNLOCK(part);
}
}
@@ -823,8 +867,9 @@ mmcsd_detach(device_t dev)
/* kill disk */
disk_destroy(part->disk);
- MMCSD_PART_LOCK_DESTROY(part);
+ MMCSD_DISK_LOCK_DESTROY(part);
}
+ MMCSD_IOCTL_LOCK_DESTROY(part);
free(part, M_DEVBUF);
}
}
@@ -844,19 +889,27 @@ mmcsd_suspend(device_t dev)
for (i = 0; i < MMC_PART_MAX; i++) {
part = sc->part[i];
- if (part != NULL && part->disk != NULL) {
- MMCSD_PART_LOCK(part);
- part->suspend = 1;
- if (part->running > 0) {
- /* kill thread */
- part->running = 0;
- wakeup(part);
- /* wait for thread to finish. */
- while (part->running != -1)
- msleep(part, &part->part_mtx, 0,
- "detach", 0);
+ if (part != NULL) {
+ if (part->disk != NULL) {
+ MMCSD_DISK_LOCK(part);
+ part->suspend = 1;
+ if (part->running > 0) {
+ /* kill thread */
+ part->running = 0;
+ wakeup(part);
+ /* wait for thread to finish. */
+ while (part->running != -1)
+ msleep(part, &part->disk_mtx, 0,
+ "mmcsd disk suspension", 0);
+ }
+ MMCSD_DISK_UNLOCK(part);
}
- MMCSD_PART_UNLOCK(part);
+ MMCSD_IOCTL_LOCK(part);
+ while (part->ioctl > 0)
+ msleep(part, &part->ioctl_mtx, 0,
+ "mmcsd IOCTL suspension", 0);
+ part->ioctl = -1;
+ MMCSD_IOCTL_UNLOCK(part);
}
}
#else /* __rtems__ */
@@ -875,16 +928,22 @@ mmcsd_resume(device_t dev)
for (i = 0; i < MMC_PART_MAX; i++) {
part = sc->part[i];
- if (part != NULL && part->disk != NULL) {
- MMCSD_PART_LOCK(part);
- part->suspend = 0;
- if (part->running <= 0) {
- part->running = 1;
- kproc_create(&mmcsd_task, part, &part->p, 0, 0,
- "%s%d: mmc/sd card", part->name, part->cnt);
- MMCSD_PART_UNLOCK(part);
- } else
- MMCSD_PART_UNLOCK(part);
+ if (part != NULL) {
+ if (part->disk != NULL) {
+ MMCSD_DISK_LOCK(part);
+ part->suspend = 0;
+ if (part->running <= 0) {
+ part->running = 1;
+ MMCSD_DISK_UNLOCK(part);
+ kproc_create(&mmcsd_task, part,
+ &part->p, 0, 0, "%s%d: mmc/sd card",
+ part->name, part->cnt);
+ } else
+ MMCSD_DISK_UNLOCK(part);
+ }
+ MMCSD_IOCTL_LOCK(part);
+ part->ioctl = 0;
+ MMCSD_IOCTL_UNLOCK(part);
}
}
#else /* __rtems__ */
@@ -916,13 +975,13 @@ mmcsd_strategy(struct bio *bp)
part = bp->bio_disk->d_drv1;
sc = part->sc;
- MMCSD_PART_LOCK(part);
+ MMCSD_DISK_LOCK(part);
if (part->running > 0 || part->suspend > 0) {
bioq_disksort(&part->bio_queue, bp);
- MMCSD_PART_UNLOCK(part);
+ MMCSD_DISK_UNLOCK(part);
wakeup(part);
} else {
- MMCSD_PART_UNLOCK(part);
+ MMCSD_DISK_UNLOCK(part);
biofinish(bp, NULL, ENXIO);
}
}
@@ -961,9 +1020,9 @@ mmcsd_ioctl(struct mmcsd_part *part, u_long cmd, void *data, int fflag)
switch (cmd) {
case MMC_IOC_CMD:
mic = data;
- err = mmcsd_ioctl_cmd(part, data, fflag);
+ err = mmcsd_ioctl_cmd(part, mic, fflag);
break;
- case MMC_IOC_CMD_MULTI:
+ case MMC_IOC_MULTI_CMD:
mimc = data;
if (mimc->num_of_cmds == 0)
break;
@@ -973,12 +1032,12 @@ mmcsd_ioctl(struct mmcsd_part *part, u_long cmd, void *data, int fflag)
size = sizeof(*mic) * cnt;
mic = malloc(size, M_TEMP, M_WAITOK);
err = copyin((const void *)mimc->cmds, mic, size);
- if (err != 0)
- break;
- for (i = 0; i < cnt; i++) {
- err = mmcsd_ioctl_cmd(part, &mic[i], fflag);
- if (err != 0)
- break;
+ if (err == 0) {
+ for (i = 0; i < cnt; i++) {
+ err = mmcsd_ioctl_cmd(part, &mic[i], fflag);
+ if (err != 0)
+ break;
+ }
}
free(mic, M_TEMP);
break;
@@ -1007,11 +1066,31 @@ mmcsd_ioctl_cmd(struct mmcsd_part *part, struct mmc_ioc_cmd *mic, int fflag)
if (part->ro == TRUE && mic->write_flag != 0)
return (EROFS);
+ /*
+ * We don't need to explicitly lock against the disk(9) half of this
+ * driver as MMCBUS_ACQUIRE_BUS() will serialize us. However, it's
+ * necessary to protect against races with detachment and suspension,
+ * especially since it's required to switch away from RPMB partitions
+ * again after an access (see mmcsd_switch_part()).
+ */
+ MMCSD_IOCTL_LOCK(part);
+ while (part->ioctl != 0) {
+ if (part->ioctl < 0) {
+ MMCSD_IOCTL_UNLOCK(part);
+ return (ENXIO);
+ }
+ msleep(part, &part->ioctl_mtx, 0, "mmcsd IOCTL", 0);
+ }
+ part->ioctl = 1;
+ MMCSD_IOCTL_UNLOCK(part);
+
err = 0;
dp = NULL;
len = mic->blksz * mic->blocks;
- if (len > MMC_IOC_MAX_BYTES)
- return (EOVERFLOW);
+ if (len > MMC_IOC_MAX_BYTES) {
+ err = EOVERFLOW;
+ goto out;
+ }
if (len != 0) {
dp = malloc(len, M_TEMP, M_WAITOK);
err = copyin((void *)(uintptr_t)mic->data_ptr, dp, len);
@@ -1066,7 +1145,7 @@ mmcsd_ioctl_cmd(struct mmcsd_part *part, struct mmc_ioc_cmd *mic, int fflag)
err = mmcsd_set_blockcount(sc, mic->blocks,
mic->write_flag & (1 << 31));
if (err != MMC_ERR_NONE)
- goto release;
+ goto switch_back;
}
if (mic->is_acmd != 0)
(void)mmc_wait_for_app_cmd(mmcbr, dev, rca, &cmd, 0);
@@ -1088,6 +1167,7 @@ mmcsd_ioctl_cmd(struct mmcsd_part *part, struct mmc_ioc_cmd *mic, int fflag)
DELAY(1000);
} while (retries-- > 0);
+switch_back:
/* ... and always switch back to the default partition. */
err = mmcsd_switch_part(mmcbr, dev, rca,
EXT_CSD_PART_CONFIG_ACC_DEFAULT);
@@ -1138,6 +1218,10 @@ release:
err = EIO;
out:
+ MMCSD_IOCTL_LOCK(part);
+ part->ioctl = 0;
+ MMCSD_IOCTL_UNLOCK(part);
+ wakeup(part);
if (dp != NULL)
free(dp, M_TEMP);
return (err);
@@ -1191,10 +1275,23 @@ mmcsd_switch_part(device_t bus, device_t dev, uint16_t rca, u_int part)
sc = device_get_softc(dev);
- if (sc->part_curr == part)
+ if (sc->mode == mode_sd)
return (MMC_ERR_NONE);
- if (sc->mode == mode_sd)
+ /*
+ * According to section "6.2.2 Command restrictions" of the eMMC
+ * specification v5.1, CMD19/CMD21 aren't allowed to be used with
+ * RPMB partitions. So we pause re-tuning along with triggering
+ * it up-front to decrease the likelihood of re-tuning becoming
+ * necessary while accessing an RPMB partition. Consequently, an
+ * RPMB partition should immediately be switched away from again
+ * after an access in order to allow for re-tuning to take place
+ * anew.
+ */
+ if (part == EXT_CSD_PART_CONFIG_ACC_RPMB)
+ MMCBUS_RETUNE_PAUSE(sc->mmcbr, sc->dev, true);
+
+ if (sc->part_curr == part)
return (MMC_ERR_NONE);
value = (sc->ext_csd[EXT_CSD_PART_CONFIG] &
@@ -1202,10 +1299,15 @@ mmcsd_switch_part(device_t bus, device_t dev, uint16_t rca, u_int part)
/* Jump! */
err = mmc_switch(bus, dev, rca, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_PART_CONFIG, value, sc->part_time, true);
- if (err != MMC_ERR_NONE)
+ if (err != MMC_ERR_NONE) {
+ if (part == EXT_CSD_PART_CONFIG_ACC_RPMB)
+ MMCBUS_RETUNE_UNPAUSE(sc->mmcbr, sc->dev);
return (err);
+ }
sc->ext_csd[EXT_CSD_PART_CONFIG] = value;
+ if (sc->part_curr == EXT_CSD_PART_CONFIG_ACC_RPMB)
+ MMCBUS_RETUNE_UNPAUSE(sc->mmcbr, sc->dev);
sc->part_curr = part;
return (MMC_ERR_NONE);
}
@@ -1217,7 +1319,7 @@ mmcsd_errmsg(int e)
if (e < 0 || e > MMC_ERR_MAX)
return "Bad error code";
- return errmsg[e];
+ return (errmsg[e]);
}
static daddr_t
@@ -1230,7 +1332,7 @@ mmcsd_rw(struct mmcsd_part *part, struct bio *bp)
struct mmc_data data;
struct mmcsd_softc *sc;
device_t dev, mmcbr;
- int numblocks, sz;
+ u_int numblocks, sz;
char *vaddr;
sc = part->sc;
@@ -1242,7 +1344,7 @@ mmcsd_rw(struct mmcsd_part *part, struct bio *bp)
end = bp->bio_pblkno + (bp->bio_bcount / sz);
while (block < end) {
vaddr = bp->bio_data + (block - bp->bio_pblkno) * sz;
- numblocks = min(end - block, mmc_get_max_data(dev));
+ numblocks = min(end - block, sc->max_data);
memset(&req, 0, sizeof(req));
memset(&cmd, 0, sizeof(cmd));
memset(&stop, 0, sizeof(stop));
@@ -1262,7 +1364,7 @@ mmcsd_rw(struct mmcsd_part *part, struct bio *bp)
cmd.opcode = MMC_WRITE_BLOCK;
}
cmd.arg = block;
- if (!mmc_get_high_cap(dev))
+ if (sc->high_cap == 0)
cmd.arg <<= 9;
cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
data.data = vaddr;
@@ -1302,7 +1404,7 @@ mmcsd_delete(struct mmcsd_part *part, struct bio *bp)
struct mmc_request req;
struct mmcsd_softc *sc;
device_t dev, mmcbr;
- int erase_sector, sz;
+ u_int erase_sector, sz;
sc = part->sc;
dev = sc->dev;
@@ -1317,7 +1419,7 @@ mmcsd_delete(struct mmcsd_part *part, struct bio *bp)
if (end >= part->eblock && end < part->eend)
end = part->eend;
/* Safe round to the erase sector boundaries. */
- erase_sector = mmc_get_erase_sector(dev);
+ erase_sector = sc->erase_sector;
start = block + erase_sector - 1; /* Round up. */
start -= start % erase_sector;
stop = end; /* Round down. */
@@ -1329,6 +1431,12 @@ mmcsd_delete(struct mmcsd_part *part, struct bio *bp)
return (end);
}
+ /*
+ * Pause re-tuning so it won't interfere with the order of erase
+ * commands. Note that these latter don't use the data lines, so
+ * re-tuning shouldn't actually become necessary during erase.
+ */
+ MMCBUS_RETUNE_PAUSE(mmcbr, dev, false);
/* Set erase start position. */
memset(&req, 0, sizeof(req));
memset(&cmd, 0, sizeof(cmd));
@@ -1339,13 +1447,15 @@ mmcsd_delete(struct mmcsd_part *part, struct bio *bp)
else
cmd.opcode = MMC_ERASE_GROUP_START;
cmd.arg = start;
- if (!mmc_get_high_cap(dev))
+ if (sc->high_cap == 0)
cmd.arg <<= 9;
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
MMCBUS_WAIT_FOR_REQUEST(mmcbr, dev, &req);
if (req.cmd->error != MMC_ERR_NONE) {
- printf("erase err1: %d\n", req.cmd->error);
- return (block);
+ device_printf(dev, "Setting erase start position failed %d\n",
+ req.cmd->error);
+ block = bp->bio_pblkno;
+ goto unpause;
}
/* Set erase stop position. */
memset(&req, 0, sizeof(req));
@@ -1356,14 +1466,16 @@ mmcsd_delete(struct mmcsd_part *part, struct bio *bp)
else
cmd.opcode = MMC_ERASE_GROUP_END;
cmd.arg = stop;
- if (!mmc_get_high_cap(dev))
+ if (sc->high_cap == 0)
cmd.arg <<= 9;
cmd.arg--;
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
MMCBUS_WAIT_FOR_REQUEST(mmcbr, dev, &req);
if (req.cmd->error != MMC_ERR_NONE) {
- printf("erase err2: %d\n", req.cmd->error);
- return (block);
+ device_printf(dev, "Setting erase stop position failed %d\n",
+ req.cmd->error);
+ block = bp->bio_pblkno;
+ goto unpause;
}
/* Erase range. */
memset(&req, 0, sizeof(req));
@@ -1374,8 +1486,11 @@ mmcsd_delete(struct mmcsd_part *part, struct bio *bp)
cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
MMCBUS_WAIT_FOR_REQUEST(mmcbr, dev, &req);
if (req.cmd->error != MMC_ERR_NONE) {
- printf("erase err3 %d\n", req.cmd->error);
- return (block);
+ device_printf(dev, "erase err3: %d\n", req.cmd->error);
+ device_printf(dev, "Issuing erase command failed %d\n",
+ req.cmd->error);
+ block = bp->bio_pblkno;
+ goto unpause;
}
/* Store one of remaining parts for the next call. */
if (bp->bio_pblkno >= part->eblock || block == start) {
@@ -1385,7 +1500,10 @@ mmcsd_delete(struct mmcsd_part *part, struct bio *bp)
part->eblock = block; /* Predict next backward. */
part->eend = start;
}
- return (end);
+ block = end;
+unpause:
+ MMCBUS_RETUNE_UNPAUSE(mmcbr, dev);
+ return (block);
}
static int
@@ -1446,16 +1564,16 @@ mmcsd_task(void *arg)
mmcbr = sc->mmcbr;
while (1) {
- MMCSD_PART_LOCK(part);
+ MMCSD_DISK_LOCK(part);
do {
if (part->running == 0)
goto out;
bp = bioq_takefirst(&part->bio_queue);
if (bp == NULL)
- msleep(part, &part->part_mtx, PRIBIO,
- "jobqueue", 0);
+ msleep(part, &part->disk_mtx, PRIBIO,
+ "mmcsd disk jobqueue", 0);
} while (bp == NULL);
- MMCSD_PART_UNLOCK(part);
+ MMCSD_DISK_UNLOCK(part);
if (bp->bio_cmd != BIO_READ && part->ro) {
bp->bio_error = EROFS;
bp->bio_resid = bp->bio_bcount;
@@ -1496,7 +1614,7 @@ release:
out:
/* tell parent we're done */
part->running = -1;
- MMCSD_PART_UNLOCK(part);
+ MMCSD_DISK_UNLOCK(part);
wakeup(part);
kproc_exit(0);