git: 44682688f038 - main - mmc_da: implement d_dump method, sddadump
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 12 Jan 2022 07:03:23 UTC
The branch main has been updated by avg:
URL: https://cgit.FreeBSD.org/src/commit/?id=44682688f038edbf34591b25ce36412a7f2d6d07
commit 44682688f038edbf34591b25ce36412a7f2d6d07
Author: Andriy Gapon <avg@FreeBSD.org>
AuthorDate: 2022-01-12 07:01:29 +0000
Commit: Andriy Gapon <avg@FreeBSD.org>
CommitDate: 2022-01-12 07:02:47 +0000
mmc_da: implement d_dump method, sddadump
sddadump has been derived from sddastart.
mmc_sim interface has grown a new method, cam_poll, to support polled
operation.
mmc_sim code has been changed to provide a sim_poll hook only if the
controller implements the new method. The hooks is implemented in terms
of the new mmc_sim_cam_poll method.
Additionally, in-progress CCB-s now have CAM_REQ_INPROG status to
satisfy xpt_pollwait().
mmc_sim_cam_poll method has been implemented in dwmmc host controller.
Reviewed by: manu, mav, imp
MFC after: 2 weeks
Relnotes: perhaps
Differential Revision: https://reviews.freebsd.org/D33843
---
sys/cam/mmc/mmc_da.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++
sys/cam/mmc/mmc_sim.c | 20 +++++++------
sys/cam/mmc/mmc_sim_if.m | 4 +++
sys/dev/mmc/host/dwmmc.c | 15 ++++++++++
4 files changed, 103 insertions(+), 9 deletions(-)
diff --git a/sys/cam/mmc/mmc_da.c b/sys/cam/mmc/mmc_da.c
index 0dfa43f4679b..8740421e416b 100644
--- a/sys/cam/mmc/mmc_da.c
+++ b/sys/cam/mmc/mmc_da.c
@@ -164,6 +164,7 @@ static const char *mmc_errmsg[] =
#define ccb_bp ppriv_ptr1
static disk_strategy_t sddastrategy;
+static dumper_t sddadump;
static periph_init_t sddainit;
static void sddaasync(void *callback_arg, u_int32_t code,
struct cam_path *path, void *arg);
@@ -1570,6 +1571,8 @@ sdda_add_part(struct cam_periph *periph, u_int type, const char *name,
part->disk->d_open = sddaopen;
part->disk->d_close = sddaclose;
part->disk->d_strategy = sddastrategy;
+ if (cam_sim_pollable(periph->sim))
+ part->disk->d_dump = sddadump;
part->disk->d_getattr = sddagetattr;
part->disk->d_gone = sddadiskgonecb;
part->disk->d_name = part->name;
@@ -2005,4 +2008,74 @@ sddaerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
{
return(cam_periph_error(ccb, cam_flags, sense_flags));
}
+
+static int
+sddadump(void *arg, void *virtual, vm_offset_t physical, off_t offset,
+ size_t length)
+{
+ struct ccb_mmcio mmcio;
+ struct disk *dp;
+ struct sdda_part *part;
+ struct sdda_softc *softc;
+ struct cam_periph *periph;
+ struct mmc_params *mmcp;
+ uint16_t count;
+ uint16_t opcode;
+ int error;
+
+ dp = arg;
+ part = dp->d_drv1;
+ softc = part->sc;
+ periph = softc->periph;
+ mmcp = &periph->path->device->mmc_ident_data;
+
+ if (softc->state != SDDA_STATE_NORMAL)
+ return (ENXIO);
+
+ count = length / 512;
+ if (count == 0)
+ return (0);
+
+ if (softc->part[softc->part_curr] != part)
+ return (EIO); /* TODO implement polled partition switch */
+
+ memset(&mmcio, 0, sizeof(mmcio));
+ xpt_setup_ccb(&mmcio.ccb_h, periph->path, CAM_PRIORITY_NORMAL); /* XXX needed? */
+
+ mmcio.ccb_h.func_code = XPT_MMC_IO;
+ mmcio.ccb_h.flags = CAM_DIR_OUT;
+ mmcio.ccb_h.retry_count = 0;
+ mmcio.ccb_h.timeout = 15 * 1000;
+
+ if (count > 1)
+ opcode = MMC_WRITE_MULTIPLE_BLOCK;
+ else
+ opcode = MMC_WRITE_BLOCK;
+ mmcio.cmd.opcode = opcode;
+ mmcio.cmd.arg = offset / 512;
+ if (!(mmcp->card_features & CARD_FEATURE_SDHC))
+ mmcio.cmd.arg <<= 9;
+
+ mmcio.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+ mmcio.cmd.data = softc->mmcdata;
+ memset(mmcio.cmd.data, 0, sizeof(struct mmc_data));
+ mmcio.cmd.data->data = virtual;
+ mmcio.cmd.data->len = 512 * count;
+ mmcio.cmd.data->flags = MMC_DATA_WRITE;
+
+ /* Direct h/w to issue CMD12 upon completion */
+ if (count > 1) {
+ mmcio.cmd.data->flags |= MMC_DATA_MULTI;
+ mmcio.stop.opcode = MMC_STOP_TRANSMISSION;
+ mmcio.stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
+ mmcio.stop.arg = 0;
+ }
+
+ error = cam_periph_runccb((union ccb *)&mmcio, cam_periph_error,
+ 0, SF_NO_RECOVERY | SF_NO_RETRY, NULL);
+ if (error != 0)
+ printf("Aborting dump due to I/O error.\n");
+ return (error);
+}
+
#endif /* _KERNEL */
diff --git a/sys/cam/mmc/mmc_sim.c b/sys/cam/mmc/mmc_sim.c
index 792551a93511..40330958574b 100644
--- a/sys/cam/mmc/mmc_sim.c
+++ b/sys/cam/mmc/mmc_sim.c
@@ -46,8 +46,10 @@ __FBSDID("$FreeBSD$");
static void
mmc_cam_default_poll(struct cam_sim *sim)
{
+ struct mmc_sim *mmc_sim;
- return;
+ mmc_sim = cam_sim_softc(sim);
+ MMC_SIM_CAM_POLL(mmc_sim->dev);
}
static void
@@ -97,12 +99,6 @@ mmc_cam_sim_default_action(struct cam_sim *sim, union ccb *ccb)
mmc_sim = cam_sim_softc(sim);
- if (mmc_sim == NULL) {
- ccb->ccb_h.status = CAM_SEL_TIMEOUT;
- xpt_done(ccb);
- return;
- }
-
mtx_assert(&mmc_sim->mtx, MA_OWNED);
if (mmc_sim->ccb != NULL) {
@@ -172,7 +168,6 @@ mmc_cam_sim_default_action(struct cam_sim *sim, union ccb *ccb)
break;
case XPT_MMC_IO:
{
- ccb->ccb_h.status = CAM_REQ_INVALID;
rv = MMC_SIM_CAM_REQUEST(mmc_sim->dev, ccb);
if (rv != 0)
ccb->ccb_h.status = CAM_SIM_QUEUED;
@@ -191,6 +186,8 @@ mmc_cam_sim_default_action(struct cam_sim *sim, union ccb *ccb)
int
mmc_cam_sim_alloc(device_t dev, const char *name, struct mmc_sim *mmc_sim)
{
+ kobjop_desc_t kobj_desc;
+ kobj_method_t *kobj_method;
mmc_sim->dev = dev;
@@ -200,8 +197,13 @@ mmc_cam_sim_alloc(device_t dev, const char *name, struct mmc_sim *mmc_sim)
snprintf(mmc_sim->name, sizeof(mmc_sim->name), "%s_sim", name);
mtx_init(&mmc_sim->mtx, mmc_sim->name, NULL, MTX_DEF);
+
+ /* Provide sim_poll hook only if the device has the poll method. */
+ kobj_desc = &mmc_sim_cam_poll_desc;
+ kobj_method = kobj_lookup_method(((kobj_t)dev)->ops->cls, NULL,
+ kobj_desc);
mmc_sim->sim = cam_sim_alloc(mmc_cam_sim_default_action,
- mmc_cam_default_poll,
+ kobj_method == &kobj_desc->deflt ? NULL : mmc_cam_default_poll,
mmc_sim->name, mmc_sim, device_get_unit(dev),
&mmc_sim->mtx, 1, 1, mmc_sim->devq);
diff --git a/sys/cam/mmc/mmc_sim_if.m b/sys/cam/mmc/mmc_sim_if.m
index f1b88fc05ef5..f7d3f4df5ebb 100644
--- a/sys/cam/mmc/mmc_sim_if.m
+++ b/sys/cam/mmc/mmc_sim_if.m
@@ -52,3 +52,7 @@ METHOD int cam_request {
device_t dev;
union ccb *ccb;
};
+
+METHOD void cam_poll {
+ device_t dev;
+};
diff --git a/sys/dev/mmc/host/dwmmc.c b/sys/dev/mmc/host/dwmmc.c
index 2080a973564f..70bd204069bd 100644
--- a/sys/dev/mmc/host/dwmmc.c
+++ b/sys/dev/mmc/host/dwmmc.c
@@ -38,12 +38,14 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/conf.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/module.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
+#include <sys/proc.h>
#include <sys/rman.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>
@@ -459,6 +461,9 @@ dwmmc_handle_card_present(struct dwmmc_softc *sc, bool is_present)
{
bool was_present;
+ if (dumping || SCHEDULER_STOPPED())
+ return;
+
was_present = sc->child != NULL;
if (!was_present && is_present) {
@@ -1543,6 +1548,15 @@ dwmmc_cam_request(device_t dev, union ccb *ccb)
return (0);
}
+
+static void
+dwmmc_cam_poll(device_t dev)
+{
+ struct dwmmc_softc *sc;
+
+ sc = device_get_softc(dev);
+ dwmmc_intr(sc);
+}
#endif /* MMCCAM */
static device_method_t dwmmc_methods[] = {
@@ -1564,6 +1578,7 @@ static device_method_t dwmmc_methods[] = {
DEVMETHOD(mmc_sim_get_tran_settings, dwmmc_get_tran_settings),
DEVMETHOD(mmc_sim_set_tran_settings, dwmmc_set_tran_settings),
DEVMETHOD(mmc_sim_cam_request, dwmmc_cam_request),
+ DEVMETHOD(mmc_sim_cam_poll, dwmmc_cam_poll),
DEVMETHOD(bus_add_child, bus_generic_add_child),
#endif