Implement d_discard for wd.
This commit is contained in:
parent
05d075b3ae
commit
7c5b45490e
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: wd.c,v 1.409 2014/07/25 08:10:36 dholland Exp $ */
|
/* $NetBSD: wd.c,v 1.410 2014/07/25 08:22:08 dholland Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved.
|
* Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved.
|
||||||
|
@ -54,7 +54,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.409 2014/07/25 08:10:36 dholland Exp $");
|
__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.410 2014/07/25 08:22:08 dholland Exp $");
|
||||||
|
|
||||||
#include "opt_ata.h"
|
#include "opt_ata.h"
|
||||||
|
|
||||||
|
@ -140,6 +140,7 @@ dev_type_ioctl(wdioctl);
|
||||||
dev_type_strategy(wdstrategy);
|
dev_type_strategy(wdstrategy);
|
||||||
dev_type_dump(wddump);
|
dev_type_dump(wddump);
|
||||||
dev_type_size(wdsize);
|
dev_type_size(wdsize);
|
||||||
|
static dev_type_discard(wddiscard);
|
||||||
|
|
||||||
const struct bdevsw wd_bdevsw = {
|
const struct bdevsw wd_bdevsw = {
|
||||||
.d_open = wdopen,
|
.d_open = wdopen,
|
||||||
|
@ -148,7 +149,7 @@ const struct bdevsw wd_bdevsw = {
|
||||||
.d_ioctl = wdioctl,
|
.d_ioctl = wdioctl,
|
||||||
.d_dump = wddump,
|
.d_dump = wddump,
|
||||||
.d_psize = wdsize,
|
.d_psize = wdsize,
|
||||||
.d_discard = nodiscard,
|
.d_discard = wddiscard,
|
||||||
.d_flag = D_DISK
|
.d_flag = D_DISK
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -163,7 +164,7 @@ const struct cdevsw wd_cdevsw = {
|
||||||
.d_poll = nopoll,
|
.d_poll = nopoll,
|
||||||
.d_mmap = nommap,
|
.d_mmap = nommap,
|
||||||
.d_kqfilter = nokqfilter,
|
.d_kqfilter = nokqfilter,
|
||||||
.d_discard = nodiscard,
|
.d_discard = wddiscard,
|
||||||
.d_flag = D_DISK
|
.d_flag = D_DISK
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -195,7 +196,7 @@ void wdrestart(void *);
|
||||||
void wddone(void *);
|
void wddone(void *);
|
||||||
int wd_get_params(struct wd_softc *, u_int8_t, struct ataparams *);
|
int wd_get_params(struct wd_softc *, u_int8_t, struct ataparams *);
|
||||||
int wd_flushcache(struct wd_softc *, int);
|
int wd_flushcache(struct wd_softc *, int);
|
||||||
int wd_trim(struct wd_softc *, int, struct disk_discard_range *);
|
int wd_trim(struct wd_softc *, int, daddr_t, long);
|
||||||
bool wd_shutdown(device_t, int);
|
bool wd_shutdown(device_t, int);
|
||||||
|
|
||||||
int wd_getcache(struct wd_softc *, int *);
|
int wd_getcache(struct wd_softc *, int *);
|
||||||
|
@ -1562,8 +1563,12 @@ wdioctl(dev_t dev, u_long xfer, void *addr, int flag, struct lwp *l)
|
||||||
aprint_debug_dev(wd->sc_dev, "TRIM maxsize %ld\n", tp->maxsize);
|
aprint_debug_dev(wd->sc_dev, "TRIM maxsize %ld\n", tp->maxsize);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case DIOCDISCARD:
|
case DIOCDISCARD: {
|
||||||
return wd_trim(wd, WDPART(dev), (struct disk_discard_range *)addr);
|
struct disk_discard_range *dr;
|
||||||
|
|
||||||
|
dr = addr;
|
||||||
|
return wd_trim(wd, WDPART(dev), dr->bno, dr->size);
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return ENOTTY;
|
return ENOTTY;
|
||||||
|
@ -1574,6 +1579,47 @@ wdioctl(dev_t dev, u_long xfer, void *addr, int flag, struct lwp *l)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
wddiscard(dev_t dev, off_t pos, off_t len)
|
||||||
|
{
|
||||||
|
struct wd_softc *wd = device_lookup_private(&wd_cd, WDUNIT(dev));
|
||||||
|
daddr_t bno;
|
||||||
|
long size, done;
|
||||||
|
long maxatonce, amount;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (!(wd->sc_params.atap_ata_major & WDC_VER_ATA7)
|
||||||
|
|| !(wd->sc_params.support_dsm & ATA_SUPPORT_DSM_TRIM)) {
|
||||||
|
/* not supported; ignore request */
|
||||||
|
ATADEBUG_PRINT(("wddiscard (unsupported)\n"), DEBUG_FUNCS);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
maxatonce = 0xffff; /*wd->sc_params.max_dsm_blocks*/
|
||||||
|
|
||||||
|
ATADEBUG_PRINT(("wddiscard\n"), DEBUG_FUNCS);
|
||||||
|
|
||||||
|
if ((wd->sc_flags & WDF_LOADED) == 0)
|
||||||
|
return EIO;
|
||||||
|
|
||||||
|
/* round the start up and the end down */
|
||||||
|
bno = (pos + DEV_BSIZE - 1) >> DEV_BSHIFT;
|
||||||
|
size = ((pos + len) >> DEV_BSHIFT) - bno;
|
||||||
|
|
||||||
|
done = 0;
|
||||||
|
while (done < size) {
|
||||||
|
amount = size - done;
|
||||||
|
if (amount > maxatonce) {
|
||||||
|
amount = maxatonce;
|
||||||
|
}
|
||||||
|
result = wd_trim(wd, WDPART(dev), bno + done, amount);
|
||||||
|
if (result) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
done += amount;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef B_FORMAT
|
#ifdef B_FORMAT
|
||||||
int
|
int
|
||||||
wdformat(struct buf *bp)
|
wdformat(struct buf *bp)
|
||||||
|
@ -1940,11 +1986,10 @@ wd_flushcache(struct wd_softc *wd, int flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
wd_trim(struct wd_softc *wd, int part, struct disk_discard_range *tr)
|
wd_trim(struct wd_softc *wd, int part, daddr_t bno, long size)
|
||||||
{
|
{
|
||||||
struct ata_command ata_c;
|
struct ata_command ata_c;
|
||||||
unsigned char *req;
|
unsigned char *req;
|
||||||
daddr_t bno = tr->bno;
|
|
||||||
|
|
||||||
if (part != RAW_PART)
|
if (part != RAW_PART)
|
||||||
bno += wd->sc_dk.dk_label->d_partitions[part].p_offset;;
|
bno += wd->sc_dk.dk_label->d_partitions[part].p_offset;;
|
||||||
|
@ -1956,8 +2001,8 @@ wd_trim(struct wd_softc *wd, int part, struct disk_discard_range *tr)
|
||||||
req[3] = (bno >> 24) & 0xff;
|
req[3] = (bno >> 24) & 0xff;
|
||||||
req[4] = (bno >> 32) & 0xff;
|
req[4] = (bno >> 32) & 0xff;
|
||||||
req[5] = (bno >> 40) & 0xff;
|
req[5] = (bno >> 40) & 0xff;
|
||||||
req[6] = tr->size & 0xff;
|
req[6] = size & 0xff;
|
||||||
req[7] = (tr->size >> 8) & 0xff;
|
req[7] = (size >> 8) & 0xff;
|
||||||
|
|
||||||
memset(&ata_c, 0, sizeof(struct ata_command));
|
memset(&ata_c, 0, sizeof(struct ata_command));
|
||||||
ata_c.r_command = ATA_DATA_SET_MANAGEMENT;
|
ata_c.r_command = ATA_DATA_SET_MANAGEMENT;
|
||||||
|
|
Loading…
Reference in New Issue