Author: ian
Date: Sat Mar  2 23:20:47 2019
New Revision: 344734
URL: https://svnweb.freebsd.org/changeset/base/344734

Log:
  Allow the sector size of the disk device to be configured using hints or
  FDT data.  The sector size must be a multiple of the device's page size.
  If not configured, use the historical default of the device page size.
  
  Setting the disk sector size to 512 or 4096 allows a variety of standard
  filesystems to be used on the device.  Of course you wouldn't want to be
  writing frequently to a SPI flash chip like it was a disk drive, but for
  data that gets written once (or rarely) and read often, using a standard
  filesystem is a nice convenient thing.

Modified:
  head/share/man/man4/at45d.4
  head/sys/dev/flash/at45d.c

Modified: head/share/man/man4/at45d.4
==============================================================================
--- head/share/man/man4/at45d.4 Sat Mar  2 22:28:43 2019        (r344733)
+++ head/share/man/man4/at45d.4 Sat Mar  2 23:20:47 2019        (r344734)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd February 26, 2019
+.Dd March 2, 2019
 .Dt AT45D 4
 .Os
 .Sh NAME
@@ -126,6 +126,10 @@ The following properties are optional for the
 .Nm
 device subnode:
 .Bl -tag -width indent
+.It Va freebsd,sectorsize
+The sector size of the disk created for this storage device.
+It must be a multiple of the device's page size.
+The default is the device page size.
 .It Va spi-cpha
 Empty property indicating the slave device requires shifted clock
 phase (CPHA) mode.
@@ -156,6 +160,10 @@ The chip-select number to assert when performing I/O f
 Set the high bit (1 << 31) to invert the logic level of the chip select line.
 .It Va hint.at45d.%d.mode
 The SPI mode (0-3) to use when communicating with this device.
+.It Va hint.at45d.%d.sectorsize
+The sector size of the disk created for this storage device.
+It must be a multiple of the device's page size.
+The default is the device page size.
 .El
 .Sh FILES
 .Bl -tag -width /dev/flash/at45d?

Modified: head/sys/dev/flash/at45d.c
==============================================================================
--- head/sys/dev/flash/at45d.c  Sat Mar  2 22:28:43 2019        (r344733)
+++ head/sys/dev/flash/at45d.c  Sat Mar  2 23:20:47 2019        (r344734)
@@ -288,9 +288,11 @@ at45d_detach(device_t dev)
        AT45D_UNLOCK(sc);
 
        if (err == 0 && sc->taskstate == TSTATE_STOPPED) {
-               disk_destroy(sc->disk);
-               bioq_flush(&sc->bio_queue, NULL, ENXIO);
-               free(sc->dummybuf, M_DEVBUF);
+               if (sc->disk) {
+                       disk_destroy(sc->disk);
+                       bioq_flush(&sc->bio_queue, NULL, ENXIO);
+                       free(sc->dummybuf, M_DEVBUF);
+               }
                AT45D_LOCK_DESTROY(sc);
        }
        return (err);
@@ -303,6 +305,7 @@ at45d_delayed_attach(void *xsc)
        struct at45d_mfg_info mfginfo;
        const struct at45d_flash_ident *ident;
        u_int i;
+       int sectorsize;
        uint32_t jedec;
        uint16_t pagesize;
        uint8_t status;
@@ -340,6 +343,30 @@ at45d_delayed_attach(void *xsc)
                pagesize = ident->pagesize;
        sc->pagesize = pagesize;
 
+       /*
+        * By default we set up a disk with a sector size that matches the
+        * device page size.  If there is a device hint or fdt property
+        * requesting a different size, use that, as long as it is a multiple of
+        * the device page size).
+        */
+       sectorsize = pagesize;
+#ifdef FDT
+       {
+               pcell_t size;
+               if (OF_getencprop(ofw_bus_get_node(sc->dev),
+                   "freebsd,sectorsize", &size, sizeof(size)) > 0)
+                       sectorsize = size;
+       }
+#endif
+       resource_int_value(device_get_name(sc->dev), device_get_unit(sc->dev),
+           "sectorsize", &sectorsize);
+
+       if ((sectorsize % pagesize) != 0) {
+               device_printf(sc->dev, "Invalid sectorsize %d, "
+                   "must be a multiple of %d\n", sectorsize, pagesize);
+               return;
+       }
+
        sc->dummybuf = malloc(pagesize, M_DEVBUF, M_WAITOK | M_ZERO);
 
        sc->disk = disk_alloc();
@@ -350,7 +377,7 @@ at45d_delayed_attach(void *xsc)
        sc->disk->d_name = "flash/at45d";
        sc->disk->d_drv1 = sc;
        sc->disk->d_maxsize = DFLTPHYS;
-       sc->disk->d_sectorsize = pagesize;
+       sc->disk->d_sectorsize = sectorsize;
        sc->disk->d_mediasize = pagesize * ident->pagecount;
        sc->disk->d_unit = device_get_unit(sc->dev);
        disk_create(sc->disk, DISK_VERSION);
@@ -358,9 +385,10 @@ at45d_delayed_attach(void *xsc)
        bioq_init(&sc->bio_queue);
        kproc_create(&at45d_task, sc, &sc->p, 0, 0, "task: at45d flash");
        sc->taskstate = TSTATE_RUNNING;
-       device_printf(sc->dev, "%s, %d bytes per page, %d pages; %d KBytes\n",
+       device_printf(sc->dev,
+           "%s, %d bytes per page, %d pages; %d KBytes; disk sector size %d\n",
            ident->name, pagesize, ident->pagecount,
-           (pagesize * ident->pagecount) / 1024);
+           (pagesize * ident->pagecount) / 1024, sectorsize);
 }
 
 static int
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to