Add flushing of devices on shutdown.
Note: this might print failure messages on some systems, unfortunatly the info from the device, stating if flushing is supported, cannot be trusted so the operation is always issued on all devices, just in case...
This commit is contained in:
parent
3daf7274a1
commit
93f307bbea
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=114534
@ -67,6 +67,7 @@ static void ata_boot_attach(void);
|
||||
static void ata_intr(void *);
|
||||
static int ata_getparam(struct ata_device *, u_int8_t);
|
||||
static int ata_service(struct ata_channel *);
|
||||
static void ata_flush(struct ata_device *);
|
||||
static void bswap(int8_t *, int);
|
||||
static void btrim(int8_t *, int);
|
||||
static void bpack(int8_t *, int8_t *, int);
|
||||
@ -198,9 +199,9 @@ ata_detach(device_t dev)
|
||||
s = splbio();
|
||||
#ifdef DEV_ATADISK
|
||||
if (ch->devices & ATA_ATA_MASTER && ch->device[MASTER].driver)
|
||||
ad_detach(&ch->device[MASTER], 1);
|
||||
ad_detach(&ch->device[MASTER]);
|
||||
if (ch->devices & ATA_ATA_SLAVE && ch->device[SLAVE].driver)
|
||||
ad_detach(&ch->device[SLAVE], 1);
|
||||
ad_detach(&ch->device[SLAVE]);
|
||||
#endif
|
||||
#if DEV_ATAPIALL
|
||||
if (ch->devices & ATA_ATAPI_MASTER && ch->device[MASTER].driver)
|
||||
@ -214,10 +215,12 @@ ata_detach(device_t dev)
|
||||
splx(s);
|
||||
|
||||
if (ch->device[MASTER].param) {
|
||||
ata_flush(&ch->device[MASTER]);
|
||||
free(ch->device[MASTER].param, M_ATA);
|
||||
ch->device[MASTER].param = NULL;
|
||||
}
|
||||
if (ch->device[SLAVE].param) {
|
||||
ata_flush(&ch->device[SLAVE]);
|
||||
free(ch->device[SLAVE].param, M_ATA);
|
||||
ch->device[SLAVE].param = NULL;
|
||||
}
|
||||
@ -818,9 +821,9 @@ ata_reinit(struct ata_channel *ch)
|
||||
if ((misdev = devices & ~ch->devices)) {
|
||||
#ifdef DEV_ATADISK
|
||||
if (misdev & ATA_ATA_MASTER && ch->device[MASTER].driver)
|
||||
ad_detach(&ch->device[MASTER], 0);
|
||||
ad_detach(&ch->device[MASTER]);
|
||||
if (misdev & ATA_ATA_SLAVE && ch->device[SLAVE].driver)
|
||||
ad_detach(&ch->device[SLAVE], 0);
|
||||
ad_detach(&ch->device[SLAVE]);
|
||||
#endif
|
||||
#if DEV_ATAPIALL
|
||||
if (misdev & ATA_ATAPI_MASTER && ch->device[MASTER].driver)
|
||||
@ -916,6 +919,32 @@ ata_service(struct ata_channel *ch)
|
||||
return ATA_OP_FINISHED;
|
||||
}
|
||||
|
||||
static void
|
||||
ata_flush(struct ata_device *atadev)
|
||||
{
|
||||
if (ata_command(atadev, ATA_C_FLUSHCACHE, 0, 0, 0, ATA_WAIT_READY))
|
||||
ata_prtdev(atadev, "flushing device failed\n");
|
||||
}
|
||||
|
||||
static void
|
||||
ata_shutdown(void *arg, int howto)
|
||||
{
|
||||
struct ata_channel *ch;
|
||||
int ctlr;
|
||||
|
||||
/* flush cache on all devices */
|
||||
for (ctlr = 0; ctlr < devclass_get_maxunit(ata_devclass); ctlr++) {
|
||||
if (!(ch = devclass_get_softc(ata_devclass, ctlr)))
|
||||
continue;
|
||||
ch->locking(ch, ATA_LF_LOCK);
|
||||
if (ch->device[MASTER].param)
|
||||
ata_flush(&ch->device[MASTER]);
|
||||
if (ch->device[SLAVE].param)
|
||||
ata_flush(&ch->device[SLAVE]);
|
||||
ch->locking(ch, ATA_LF_UNLOCK);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ata_wait(struct ata_device *atadev, u_int8_t mask)
|
||||
{
|
||||
@ -1538,5 +1567,10 @@ ata_init(void)
|
||||
printf("ata: config_intrhook_establish failed\n");
|
||||
free(ata_delayed_attach, M_TEMP);
|
||||
}
|
||||
/* Register a handler to flush write caches on shutdown */
|
||||
if ((EVENTHANDLER_REGISTER(shutdown_post_sync, ata_shutdown,
|
||||
NULL, SHUTDOWN_PRI_DEFAULT)) == NULL)
|
||||
printf("ata: shutdown event registration failed!\n");
|
||||
|
||||
}
|
||||
SYSINIT(atadev, SI_SUB_DRIVERS, SI_ORDER_SECOND, ata_init, NULL)
|
||||
|
@ -53,7 +53,6 @@
|
||||
|
||||
/* prototypes */
|
||||
static disk_open_t adopen;
|
||||
static disk_close_t adclose;
|
||||
static disk_strategy_t adstrategy;
|
||||
static dumper_t addump;
|
||||
static void ad_invalidatequeue(struct ad_softc *, struct ad_request *);
|
||||
@ -186,7 +185,6 @@ ad_attach(struct ata_device *atadev)
|
||||
ATA_UNLOCK_CH(atadev->channel);
|
||||
|
||||
adp->disk.d_open = adopen;
|
||||
adp->disk.d_close = adclose;
|
||||
adp->disk.d_strategy = adstrategy;
|
||||
adp->disk.d_dump = addump;
|
||||
adp->disk.d_name = "ad";
|
||||
@ -208,7 +206,7 @@ ad_attach(struct ata_device *atadev)
|
||||
}
|
||||
|
||||
void
|
||||
ad_detach(struct ata_device *atadev, int flush) /* get rid of flush XXX SOS */
|
||||
ad_detach(struct ata_device *atadev)
|
||||
{
|
||||
struct ad_softc *adp = atadev->driver;
|
||||
struct ad_request *request;
|
||||
@ -229,10 +227,6 @@ ad_detach(struct ata_device *atadev, int flush) /* get rid of flush XXX SOS */
|
||||
if (adp->flags & AD_F_RAID_SUBDISK)
|
||||
ata_raiddisk_detach(adp);
|
||||
|
||||
if (flush) {
|
||||
if (ata_command(atadev, ATA_C_FLUSHCACHE, 0, 0, 0, ATA_WAIT_READY))
|
||||
ata_prtdev(atadev, "flushing cache on detach failed\n");
|
||||
}
|
||||
ata_free_name(atadev);
|
||||
ata_free_lun(&adp_lun_map, adp->lun);
|
||||
atadev->driver = NULL;
|
||||
@ -254,20 +248,6 @@ adopen(struct disk *dp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
adclose(struct disk *dp)
|
||||
{
|
||||
struct ad_softc *adp = dp->d_drv1;
|
||||
|
||||
adp->device->channel->locking(adp->device->channel, ATA_LF_LOCK);
|
||||
ATA_SLEEPLOCK_CH(adp->device->channel, ATA_CONTROL);
|
||||
if (ata_command(adp->device, ATA_C_FLUSHCACHE, 0, 0, 0, ATA_WAIT_READY))
|
||||
ata_prtdev(adp->device, "flushing cache on close failed\n");
|
||||
ATA_UNLOCK_CH(adp->device->channel);
|
||||
adp->device->channel->locking(adp->device->channel, ATA_LF_UNLOCK);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
adstrategy(struct bio *bp)
|
||||
{
|
||||
|
@ -75,7 +75,7 @@ struct ad_softc {
|
||||
};
|
||||
|
||||
void ad_attach(struct ata_device *);
|
||||
void ad_detach(struct ata_device *, int);
|
||||
void ad_detach(struct ata_device *);
|
||||
void ad_reinit(struct ata_device *);
|
||||
void ad_start(struct ata_device *);
|
||||
int ad_transfer(struct ad_request *);
|
||||
|
Loading…
Reference in New Issue
Block a user