Merge 985564eb3e ("Merge tag 'core-debugobjects-2022-05-23' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip") into android-mainline

Steps on the way to 5.19-rc1

Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: If0988ce99bc4e47e5d58ea208fb159f371cd73da
This commit is contained in:
Greg Kroah-Hartman
2022-06-04 12:44:36 +02:00
22 changed files with 636 additions and 336 deletions

View File

@@ -2630,14 +2630,14 @@
when set.
Format: <int>
libata.force= [LIBATA] Force configurations. The format is comma-
separated list of "[ID:]VAL" where ID is
PORT[.DEVICE]. PORT and DEVICE are decimal numbers
matching port, link or device. Basically, it matches
the ATA ID string printed on console by libata. If
the whole ID part is omitted, the last PORT and DEVICE
values are used. If ID hasn't been specified yet, the
configuration applies to all ports, links and devices.
libata.force= [LIBATA] Force configurations. The format is a comma-
separated list of "[ID:]VAL" where ID is PORT[.DEVICE].
PORT and DEVICE are decimal numbers matching port, link
or device. Basically, it matches the ATA ID string
printed on console by libata. If the whole ID part is
omitted, the last PORT and DEVICE values are used. If
ID hasn't been specified yet, the configuration applies
to all ports, links and devices.
If only DEVICE is omitted, the parameter applies to
the port and all links and devices behind it. DEVICE
@@ -2647,7 +2647,7 @@
host link and device attached to it.
The VAL specifies the configuration to force. As long
as there's no ambiguity shortcut notation is allowed.
as there is no ambiguity, shortcut notation is allowed.
For example, both 1.5 and 1.5G would work for 1.5Gbps.
The following configurations can be forced.
@@ -2660,19 +2660,58 @@
udma[/][16,25,33,44,66,100,133] notation is also
allowed.
* nohrst, nosrst, norst: suppress hard, soft and both
resets.
* rstonce: only attempt one reset during hot-unplug
link recovery.
* [no]dbdelay: Enable or disable the extra 200ms delay
before debouncing a link PHY and device presence
detection.
* [no]ncq: Turn on or off NCQ.
* [no]ncqtrim: Turn off queued DSM TRIM.
* [no]ncqtrim: Enable or disable queued DSM TRIM.
* nohrst, nosrst, norst: suppress hard, soft
and both resets.
* [no]ncqati: Enable or disable NCQ trim on ATI chipset.
* rstonce: only attempt one reset during
hot-unplug link recovery
* [no]trim: Enable or disable (unqueued) TRIM.
* dump_id: dump IDENTIFY data.
* trim_zero: Indicate that TRIM command zeroes data.
* atapi_dmadir: Enable ATAPI DMADIR bridge support
* max_trim_128m: Set 128M maximum trim size limit.
* [no]dma: Turn on or off DMA transfers.
* atapi_dmadir: Enable ATAPI DMADIR bridge support.
* atapi_mod16_dma: Enable the use of ATAPI DMA for
commands that are not a multiple of 16 bytes.
* [no]dmalog: Enable or disable the use of the
READ LOG DMA EXT command to access logs.
* [no]iddevlog: Enable or disable access to the
identify device data log.
* [no]logdir: Enable or disable access to the general
purpose log directory.
* max_sec_128: Set transfer size limit to 128 sectors.
* max_sec_1024: Set or clear transfer size limit to
1024 sectors.
* max_sec_lba48: Set or clear transfer size limit to
65535 sectors.
* [no]lpm: Enable or disable link power management.
* [no]setxfer: Indicate if transfer speed mode setting
should be skipped.
* dump_id: Dump IDENTIFY data.
* disable: Disable this device.

View File

@@ -26,6 +26,7 @@ properties:
- items:
- enum:
- renesas,sata-r8a774b1 # RZ/G2N
- renesas,sata-r8a774e1 # RZ/G2H
- renesas,sata-r8a7795 # R-Car H3
- renesas,sata-r8a77965 # R-Car M3-N
- const: renesas,rcar-gen3-sata # generic R-Car Gen3 or RZ/G2

View File

@@ -424,12 +424,6 @@ How commands are issued
-----------------------
Internal commands
First, qc is allocated and initialized using :c:func:`ata_qc_new_init`.
Although :c:func:`ata_qc_new_init` doesn't implement any wait or retry
mechanism when qc is not available, internal commands are currently
issued only during initialization and error recovery, so no other
command is active and allocation is guaranteed to succeed.
Once allocated qc's taskfile is initialized for the command to be
executed. qc currently has two mechanisms to notify completion. One
is via ``qc->complete_fn()`` callback and the other is completion
@@ -447,11 +441,6 @@ SCSI commands
translated. No qc is involved in processing a simulated scmd. The
result is computed right away and the scmd is completed.
For a translated scmd, :c:func:`ata_qc_new_init` is invoked to allocate a
qc and the scmd is translated into the qc. SCSI midlayer's
completion notification function pointer is stored into
``qc->scsidone``.
``qc->complete_fn()`` callback is used for completion notification. ATA
commands use :c:func:`ata_scsi_qc_complete` while ATAPI commands use
:c:func:`atapi_qc_complete`. Both functions end up calling ``qc->scsidone``

View File

@@ -306,8 +306,15 @@ Further notes:
Mount options
-------------
zonefs define the "errors=<behavior>" mount option to allow the user to specify
zonefs behavior in response to I/O errors, inode size inconsistencies or zone
zonefs defines several mount options:
* errors=<behavior>
* explicit-open
"errors=<behavior>" option
~~~~~~~~~~~~~~~~~~~~~~~~~~
The "errors=<behavior>" option mount option allows the user to specify zonefs
behavior in response to I/O errors, inode size inconsistencies or zone
condition changes. The defined behaviors are as follow:
* remount-ro (default)
@@ -326,6 +333,9 @@ discover the amount of data that has been written to the zone. In the case of a
read-only zone discovered at run-time, as indicated in the previous section.
The size of the zone file is left unchanged from its last updated value.
"explicit-open" option
~~~~~~~~~~~~~~~~~~~~~~
A zoned block device (e.g. an NVMe Zoned Namespace device) may have limits on
the number of zones that can be active, that is, zones that are in the
implicit open, explicit open or closed conditions. This potential limitation
@@ -341,6 +351,44 @@ guaranteed that write requests can be processed. Conversely, the
to the device on the last close() of a zone file if the zone is not full nor
empty.
Runtime sysfs attributes
------------------------
zonefs defines several sysfs attributes for mounted devices. All attributes
are user readable and can be found in the directory /sys/fs/zonefs/<dev>/,
where <dev> is the name of the mounted zoned block device.
The attributes defined are as follows.
* **max_wro_seq_files**: This attribute reports the maximum number of
sequential zone files that can be open for writing. This number corresponds
to the maximum number of explicitly or implicitly open zones that the device
supports. A value of 0 means that the device has no limit and that any zone
(any file) can be open for writing and written at any time, regardless of the
state of other zones. When the *explicit-open* mount option is used, zonefs
will fail any open() system call requesting to open a sequential zone file for
writing when the number of sequential zone files already open for writing has
reached the *max_wro_seq_files* limit.
* **nr_wro_seq_files**: This attribute reports the current number of sequential
zone files open for writing. When the "explicit-open" mount option is used,
this number can never exceed *max_wro_seq_files*. If the *explicit-open*
mount option is not used, the reported number can be greater than
*max_wro_seq_files*. In such case, it is the responsibility of the
application to not write simultaneously more than *max_wro_seq_files*
sequential zone files. Failure to do so can result in write errors.
* **max_active_seq_files**: This attribute reports the maximum number of
sequential zone files that are in an active state, that is, sequential zone
files that are partially writen (not empty nor full) or that have a zone that
is explicitly open (which happens only if the *explicit-open* mount option is
used). This number is always equal to the maximum number of active zones that
the device supports. A value of 0 means that the mounted device has no limit
on the number of sequential zone files that can be active.
* **nr_active_seq_files**: This attributes reports the current number of
sequential zone files that are active. If *max_active_seq_files* is not 0,
then the value of *nr_active_seq_files* can never exceed the value of
*nr_active_seq_files*, regardless of the use of the *explicit-open* mount
option.
Zonefs User Space Tools
=======================

View File

@@ -324,7 +324,6 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */
{ PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */
{ PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */
{ PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG/Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */
{ PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */
{ PCI_VDEVICE(INTEL, 0x1e03), board_ahci_low_power }, /* Panther M AHCI */
@@ -367,7 +366,9 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, 0x1f3e), board_ahci_avn }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f3f), board_ahci_avn }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg/Lewisburg AHCI*/
{ PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Wellsburg/Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* *burg SATA0 'RAID' */
{ PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* *burg SATA1 'RAID' */
{ PCI_VDEVICE(INTEL, 0x282f), board_ahci }, /* *burg SATA2 'RAID' */
{ PCI_VDEVICE(INTEL, 0x43d4), board_ahci }, /* Rocket Lake PCH-H RAID */
{ PCI_VDEVICE(INTEL, 0x43d5), board_ahci }, /* Rocket Lake PCH-H RAID */
{ PCI_VDEVICE(INTEL, 0x43d6), board_ahci }, /* Rocket Lake PCH-H RAID */

View File

@@ -549,15 +549,10 @@ static int brcm_ahci_remove(struct platform_device *pdev)
struct ata_host *host = dev_get_drvdata(&pdev->dev);
struct ahci_host_priv *hpriv = host->private_data;
struct brcm_ahci_priv *priv = hpriv->plat_data;
int ret;
brcm_sata_phys_disable(priv);
ret = ata_platform_remove_one(pdev);
if (ret)
return ret;
return 0;
return ata_platform_remove_one(pdev);
}
static void brcm_ahci_shutdown(struct platform_device *pdev)

View File

@@ -96,7 +96,8 @@ struct ata_force_param {
unsigned long xfer_mask;
unsigned int horkage_on;
unsigned int horkage_off;
u16 lflags;
u16 lflags_on;
u16 lflags_off;
};
struct ata_force_ent {
@@ -386,11 +387,17 @@ static void ata_force_link_limits(struct ata_link *link)
}
/* let lflags stack */
if (fe->param.lflags) {
link->flags |= fe->param.lflags;
if (fe->param.lflags_on) {
link->flags |= fe->param.lflags_on;
ata_link_notice(link,
"FORCE: link flag 0x%x forced -> 0x%x\n",
fe->param.lflags, link->flags);
fe->param.lflags_on, link->flags);
}
if (fe->param.lflags_off) {
link->flags &= ~fe->param.lflags_off;
ata_link_notice(link,
"FORCE: link flag 0x%x cleared -> 0x%x\n",
fe->param.lflags_off, link->flags);
}
}
}
@@ -898,7 +905,7 @@ EXPORT_SYMBOL_GPL(ata_xfer_mode2mask);
* RETURNS:
* Matching xfer_shift, -1 if no match found.
*/
int ata_xfer_mode2shift(unsigned long xfer_mode)
int ata_xfer_mode2shift(u8 xfer_mode)
{
const struct ata_xfer_ent *ent;
@@ -1398,7 +1405,7 @@ unsigned long ata_id_xfermask(const u16 *id)
/* But wait.. there's more. Design your standards by
* committee and you too can get a free iordy field to
* process. However its the speeds not the modes that
* process. However it is the speeds not the modes that
* are supported... Note drivers using the timing API
* will get this right anyway
*/
@@ -3898,7 +3905,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
/* Devices where NCQ should be avoided */
/* NCQ is slow */
{ "WDC WD740ADFD-00", NULL, ATA_HORKAGE_NONCQ },
{ "WDC WD740ADFD-00NLR1", NULL, ATA_HORKAGE_NONCQ, },
{ "WDC WD740ADFD-00NLR1", NULL, ATA_HORKAGE_NONCQ },
/* http://thread.gmane.org/gmane.linux.ide/14907 */
{ "FUJITSU MHT2060BH", NULL, ATA_HORKAGE_NONCQ },
/* NCQ is broken */
@@ -3924,23 +3931,23 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
/* drives which fail FPDMA_AA activation (some may freeze afterwards)
the ST disks also have LPM issues */
{ "ST1000LM024 HN-M101MBB", NULL, ATA_HORKAGE_BROKEN_FPDMA_AA |
ATA_HORKAGE_NOLPM, },
ATA_HORKAGE_NOLPM },
{ "VB0250EAVER", "HPG7", ATA_HORKAGE_BROKEN_FPDMA_AA },
/* Blacklist entries taken from Silicon Image 3124/3132
Windows driver .inf file - also several Linux problem reports */
{ "HTS541060G9SA00", "MB3OC60D", ATA_HORKAGE_NONCQ, },
{ "HTS541080G9SA00", "MB4OC60D", ATA_HORKAGE_NONCQ, },
{ "HTS541010G9SA00", "MBZOC60D", ATA_HORKAGE_NONCQ, },
{ "HTS541060G9SA00", "MB3OC60D", ATA_HORKAGE_NONCQ },
{ "HTS541080G9SA00", "MB4OC60D", ATA_HORKAGE_NONCQ },
{ "HTS541010G9SA00", "MBZOC60D", ATA_HORKAGE_NONCQ },
/* https://bugzilla.kernel.org/show_bug.cgi?id=15573 */
{ "C300-CTFDDAC128MAG", "0001", ATA_HORKAGE_NONCQ, },
{ "C300-CTFDDAC128MAG", "0001", ATA_HORKAGE_NONCQ },
/* Sandisk SD7/8/9s lock up hard on large trims */
{ "SanDisk SD[789]*", NULL, ATA_HORKAGE_MAX_TRIM_128M, },
{ "SanDisk SD[789]*", NULL, ATA_HORKAGE_MAX_TRIM_128M },
/* devices which puke on READ_NATIVE_MAX */
{ "HDS724040KLSA80", "KFAOA20N", ATA_HORKAGE_BROKEN_HPA, },
{ "HDS724040KLSA80", "KFAOA20N", ATA_HORKAGE_BROKEN_HPA },
{ "WDC WD3200JD-00KLB0", "WD-WCAMR1130137", ATA_HORKAGE_BROKEN_HPA },
{ "WDC WD2500JD-00HBB0", "WD-WMAL71490727", ATA_HORKAGE_BROKEN_HPA },
{ "MAXTOR 6L080L4", "A93.0500", ATA_HORKAGE_BROKEN_HPA },
@@ -3949,22 +3956,22 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "OCZ-VERTEX", "1.30", ATA_HORKAGE_BROKEN_HPA },
/* Devices which report 1 sector over size HPA */
{ "ST340823A", NULL, ATA_HORKAGE_HPA_SIZE, },
{ "ST320413A", NULL, ATA_HORKAGE_HPA_SIZE, },
{ "ST310211A", NULL, ATA_HORKAGE_HPA_SIZE, },
{ "ST340823A", NULL, ATA_HORKAGE_HPA_SIZE },
{ "ST320413A", NULL, ATA_HORKAGE_HPA_SIZE },
{ "ST310211A", NULL, ATA_HORKAGE_HPA_SIZE },
/* Devices which get the IVB wrong */
{ "QUANTUM FIREBALLlct10 05", "A03.0900", ATA_HORKAGE_IVB, },
{ "QUANTUM FIREBALLlct10 05", "A03.0900", ATA_HORKAGE_IVB },
/* Maybe we should just blacklist TSSTcorp... */
{ "TSSTcorp CDDVDW SH-S202[HJN]", "SB0[01]", ATA_HORKAGE_IVB, },
{ "TSSTcorp CDDVDW SH-S202[HJN]", "SB0[01]", ATA_HORKAGE_IVB },
/* Devices that do not need bridging limits applied */
{ "MTRON MSP-SATA*", NULL, ATA_HORKAGE_BRIDGE_OK, },
{ "BUFFALO HD-QSU2/R5", NULL, ATA_HORKAGE_BRIDGE_OK, },
{ "MTRON MSP-SATA*", NULL, ATA_HORKAGE_BRIDGE_OK },
{ "BUFFALO HD-QSU2/R5", NULL, ATA_HORKAGE_BRIDGE_OK },
/* Devices which aren't very happy with higher link speeds */
{ "WD My Book", NULL, ATA_HORKAGE_1_5_GBPS, },
{ "Seagate FreeAgent GoFlex", NULL, ATA_HORKAGE_1_5_GBPS, },
{ "WD My Book", NULL, ATA_HORKAGE_1_5_GBPS },
{ "Seagate FreeAgent GoFlex", NULL, ATA_HORKAGE_1_5_GBPS },
/*
* Devices which choke on SETXFER. Applies only if both the
@@ -3982,57 +3989,57 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
/* 512GB MX100 with MU01 firmware has both queued TRIM and LPM issues */
{ "Crucial_CT512MX100*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM |
ATA_HORKAGE_ZERO_AFTER_TRIM |
ATA_HORKAGE_NOLPM, },
ATA_HORKAGE_NOLPM },
/* 512GB MX100 with newer firmware has only LPM issues */
{ "Crucial_CT512MX100*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM |
ATA_HORKAGE_NOLPM, },
ATA_HORKAGE_NOLPM },
/* 480GB+ M500 SSDs have both queued TRIM and LPM issues */
{ "Crucial_CT480M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
ATA_HORKAGE_ZERO_AFTER_TRIM |
ATA_HORKAGE_NOLPM, },
ATA_HORKAGE_NOLPM },
{ "Crucial_CT960M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
ATA_HORKAGE_ZERO_AFTER_TRIM |
ATA_HORKAGE_NOLPM, },
ATA_HORKAGE_NOLPM },
/* These specific Samsung models/firmware-revs do not handle LPM well */
{ "SAMSUNG MZMPC128HBFU-000MV", "CXM14M1Q", ATA_HORKAGE_NOLPM, },
{ "SAMSUNG SSD PM830 mSATA *", "CXM13D1Q", ATA_HORKAGE_NOLPM, },
{ "SAMSUNG MZ7TD256HAFV-000L9", NULL, ATA_HORKAGE_NOLPM, },
{ "SAMSUNG MZ7TE512HMHP-000L1", "EXT06L0Q", ATA_HORKAGE_NOLPM, },
{ "SAMSUNG MZMPC128HBFU-000MV", "CXM14M1Q", ATA_HORKAGE_NOLPM },
{ "SAMSUNG SSD PM830 mSATA *", "CXM13D1Q", ATA_HORKAGE_NOLPM },
{ "SAMSUNG MZ7TD256HAFV-000L9", NULL, ATA_HORKAGE_NOLPM },
{ "SAMSUNG MZ7TE512HMHP-000L1", "EXT06L0Q", ATA_HORKAGE_NOLPM },
/* devices that don't properly handle queued TRIM commands */
{ "Micron_M500IT_*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM |
ATA_HORKAGE_ZERO_AFTER_TRIM, },
ATA_HORKAGE_ZERO_AFTER_TRIM },
{ "Micron_M500_*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
ATA_HORKAGE_ZERO_AFTER_TRIM, },
ATA_HORKAGE_ZERO_AFTER_TRIM },
{ "Crucial_CT*M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
ATA_HORKAGE_ZERO_AFTER_TRIM, },
ATA_HORKAGE_ZERO_AFTER_TRIM },
{ "Micron_M5[15]0_*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM |
ATA_HORKAGE_ZERO_AFTER_TRIM, },
ATA_HORKAGE_ZERO_AFTER_TRIM },
{ "Crucial_CT*M550*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM |
ATA_HORKAGE_ZERO_AFTER_TRIM, },
ATA_HORKAGE_ZERO_AFTER_TRIM },
{ "Crucial_CT*MX100*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM |
ATA_HORKAGE_ZERO_AFTER_TRIM, },
ATA_HORKAGE_ZERO_AFTER_TRIM },
{ "Samsung SSD 840 EVO*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
ATA_HORKAGE_NO_DMA_LOG |
ATA_HORKAGE_ZERO_AFTER_TRIM, },
ATA_HORKAGE_ZERO_AFTER_TRIM },
{ "Samsung SSD 840*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
ATA_HORKAGE_ZERO_AFTER_TRIM, },
ATA_HORKAGE_ZERO_AFTER_TRIM },
{ "Samsung SSD 850*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
ATA_HORKAGE_ZERO_AFTER_TRIM, },
ATA_HORKAGE_ZERO_AFTER_TRIM },
{ "Samsung SSD 860*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
ATA_HORKAGE_ZERO_AFTER_TRIM |
ATA_HORKAGE_NO_NCQ_ON_ATI, },
ATA_HORKAGE_NO_NCQ_ON_ATI },
{ "Samsung SSD 870*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
ATA_HORKAGE_ZERO_AFTER_TRIM |
ATA_HORKAGE_NO_NCQ_ON_ATI, },
ATA_HORKAGE_NO_NCQ_ON_ATI },
{ "FCCT*M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
ATA_HORKAGE_ZERO_AFTER_TRIM, },
ATA_HORKAGE_ZERO_AFTER_TRIM },
/* devices that don't properly handle TRIM commands */
{ "SuperSSpeed S238*", NULL, ATA_HORKAGE_NOTRIM, },
{ "M88V29*", NULL, ATA_HORKAGE_NOTRIM, },
{ "SuperSSpeed S238*", NULL, ATA_HORKAGE_NOTRIM },
{ "M88V29*", NULL, ATA_HORKAGE_NOTRIM },
/*
* As defined, the DRAT (Deterministic Read After Trim) and RZAT
@@ -4050,16 +4057,16 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
* The intel 510 drive has buggy DRAT/RZAT. Explicitly exclude
* that model before whitelisting all other intel SSDs.
*/
{ "INTEL*SSDSC2MH*", NULL, 0, },
{ "INTEL*SSDSC2MH*", NULL, 0 },
{ "Micron*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM, },
{ "Crucial*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM, },
{ "INTEL*SSD*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM, },
{ "SSD*INTEL*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM, },
{ "Samsung*SSD*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM, },
{ "SAMSUNG*SSD*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM, },
{ "SAMSUNG*MZ7KM*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM, },
{ "ST[1248][0248]0[FH]*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM, },
{ "Micron*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM },
{ "Crucial*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM },
{ "INTEL*SSD*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM },
{ "SSD*INTEL*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM },
{ "Samsung*SSD*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM },
{ "SAMSUNG*SSD*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM },
{ "SAMSUNG*MZ7KM*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM },
{ "ST[1248][0248]0[FH]*", NULL, ATA_HORKAGE_ZERO_AFTER_TRIM },
/*
* Some WD SATA-I drives spin up and down erratically when the link
@@ -4566,42 +4573,6 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
#endif /* __BIG_ENDIAN */
}
/**
* ata_qc_new_init - Request an available ATA command, and initialize it
* @dev: Device from whom we request an available command structure
* @tag: tag
*
* LOCKING:
* None.
*/
struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag)
{
struct ata_port *ap = dev->link->ap;
struct ata_queued_cmd *qc;
/* no command while frozen */
if (unlikely(ap->pflags & ATA_PFLAG_FROZEN))
return NULL;
/* libsas case */
if (ap->flags & ATA_FLAG_SAS_HOST) {
tag = ata_sas_allocate_tag(ap);
if (tag < 0)
return NULL;
}
qc = __ata_qc_from_tag(ap, tag);
qc->tag = qc->hw_tag = tag;
qc->scsicmd = NULL;
qc->ap = ap;
qc->dev = dev;
ata_qc_reinit(qc);
return qc;
}
/**
* ata_qc_free - free unused ata_queued_cmd
* @qc: Command to complete
@@ -4614,19 +4585,9 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag)
*/
void ata_qc_free(struct ata_queued_cmd *qc)
{
struct ata_port *ap;
unsigned int tag;
WARN_ON_ONCE(qc == NULL); /* ata_qc_from_tag _might_ return NULL */
ap = qc->ap;
qc->flags = 0;
tag = qc->tag;
if (ata_tag_valid(tag)) {
if (ata_tag_valid(qc->tag))
qc->tag = ATA_TAG_POISON;
if (ap->flags & ATA_FLAG_SAS_HOST)
ata_sas_free_tag(tag, ap);
}
}
void __ata_qc_complete(struct ata_queued_cmd *qc)
@@ -5605,7 +5566,7 @@ static void ata_finalize_port_ops(struct ata_port_operations *ops)
* Start and then freeze ports of @host. Started status is
* recorded in host->flags, so this function can be called
* multiple times. Ports are guaranteed to get started only
* once. If host->ops isn't initialized yet, its set to the
* once. If host->ops is not initialized yet, it is set to the
* first non-dummy port ops.
*
* LOCKING:
@@ -6146,67 +6107,113 @@ int ata_platform_remove_one(struct platform_device *pdev)
EXPORT_SYMBOL_GPL(ata_platform_remove_one);
#ifdef CONFIG_ATA_FORCE
#define force_cbl(name, flag) \
{ #name, .cbl = (flag) }
#define force_spd_limit(spd, val) \
{ #spd, .spd_limit = (val) }
#define force_xfer(mode, shift) \
{ #mode, .xfer_mask = (1UL << (shift)) }
#define force_lflag_on(name, flags) \
{ #name, .lflags_on = (flags) }
#define force_lflag_onoff(name, flags) \
{ "no" #name, .lflags_on = (flags) }, \
{ #name, .lflags_off = (flags) }
#define force_horkage_on(name, flag) \
{ #name, .horkage_on = (flag) }
#define force_horkage_onoff(name, flag) \
{ "no" #name, .horkage_on = (flag) }, \
{ #name, .horkage_off = (flag) }
static const struct ata_force_param force_tbl[] __initconst = {
force_cbl(40c, ATA_CBL_PATA40),
force_cbl(80c, ATA_CBL_PATA80),
force_cbl(short40c, ATA_CBL_PATA40_SHORT),
force_cbl(unk, ATA_CBL_PATA_UNK),
force_cbl(ign, ATA_CBL_PATA_IGN),
force_cbl(sata, ATA_CBL_SATA),
force_spd_limit(1.5Gbps, 1),
force_spd_limit(3.0Gbps, 2),
force_xfer(pio0, ATA_SHIFT_PIO + 0),
force_xfer(pio1, ATA_SHIFT_PIO + 1),
force_xfer(pio2, ATA_SHIFT_PIO + 2),
force_xfer(pio3, ATA_SHIFT_PIO + 3),
force_xfer(pio4, ATA_SHIFT_PIO + 4),
force_xfer(pio5, ATA_SHIFT_PIO + 5),
force_xfer(pio6, ATA_SHIFT_PIO + 6),
force_xfer(mwdma0, ATA_SHIFT_MWDMA + 0),
force_xfer(mwdma1, ATA_SHIFT_MWDMA + 1),
force_xfer(mwdma2, ATA_SHIFT_MWDMA + 2),
force_xfer(mwdma3, ATA_SHIFT_MWDMA + 3),
force_xfer(mwdma4, ATA_SHIFT_MWDMA + 4),
force_xfer(udma0, ATA_SHIFT_UDMA + 0),
force_xfer(udma16, ATA_SHIFT_UDMA + 0),
force_xfer(udma/16, ATA_SHIFT_UDMA + 0),
force_xfer(udma1, ATA_SHIFT_UDMA + 1),
force_xfer(udma25, ATA_SHIFT_UDMA + 1),
force_xfer(udma/25, ATA_SHIFT_UDMA + 1),
force_xfer(udma2, ATA_SHIFT_UDMA + 2),
force_xfer(udma33, ATA_SHIFT_UDMA + 2),
force_xfer(udma/33, ATA_SHIFT_UDMA + 2),
force_xfer(udma3, ATA_SHIFT_UDMA + 3),
force_xfer(udma44, ATA_SHIFT_UDMA + 3),
force_xfer(udma/44, ATA_SHIFT_UDMA + 3),
force_xfer(udma4, ATA_SHIFT_UDMA + 4),
force_xfer(udma66, ATA_SHIFT_UDMA + 4),
force_xfer(udma/66, ATA_SHIFT_UDMA + 4),
force_xfer(udma5, ATA_SHIFT_UDMA + 5),
force_xfer(udma100, ATA_SHIFT_UDMA + 5),
force_xfer(udma/100, ATA_SHIFT_UDMA + 5),
force_xfer(udma6, ATA_SHIFT_UDMA + 6),
force_xfer(udma133, ATA_SHIFT_UDMA + 6),
force_xfer(udma/133, ATA_SHIFT_UDMA + 6),
force_xfer(udma7, ATA_SHIFT_UDMA + 7),
force_lflag_on(nohrst, ATA_LFLAG_NO_HRST),
force_lflag_on(nosrst, ATA_LFLAG_NO_SRST),
force_lflag_on(norst, ATA_LFLAG_NO_HRST | ATA_LFLAG_NO_SRST),
force_lflag_on(rstonce, ATA_LFLAG_RST_ONCE),
force_lflag_onoff(dbdelay, ATA_LFLAG_NO_DEBOUNCE_DELAY),
force_horkage_onoff(ncq, ATA_HORKAGE_NONCQ),
force_horkage_onoff(ncqtrim, ATA_HORKAGE_NO_NCQ_TRIM),
force_horkage_onoff(ncqati, ATA_HORKAGE_NO_NCQ_ON_ATI),
force_horkage_onoff(trim, ATA_HORKAGE_NOTRIM),
force_horkage_on(trim_zero, ATA_HORKAGE_ZERO_AFTER_TRIM),
force_horkage_on(max_trim_128m, ATA_HORKAGE_MAX_TRIM_128M),
force_horkage_onoff(dma, ATA_HORKAGE_NODMA),
force_horkage_on(atapi_dmadir, ATA_HORKAGE_ATAPI_DMADIR),
force_horkage_on(atapi_mod16_dma, ATA_HORKAGE_ATAPI_MOD16_DMA),
force_horkage_onoff(dmalog, ATA_HORKAGE_NO_DMA_LOG),
force_horkage_onoff(iddevlog, ATA_HORKAGE_NO_ID_DEV_LOG),
force_horkage_onoff(logdir, ATA_HORKAGE_NO_LOG_DIR),
force_horkage_on(max_sec_128, ATA_HORKAGE_MAX_SEC_128),
force_horkage_on(max_sec_1024, ATA_HORKAGE_MAX_SEC_1024),
force_horkage_on(max_sec_lba48, ATA_HORKAGE_MAX_SEC_LBA48),
force_horkage_onoff(lpm, ATA_HORKAGE_NOLPM),
force_horkage_onoff(setxfer, ATA_HORKAGE_NOSETXFER),
force_horkage_on(dump_id, ATA_HORKAGE_DUMP_ID),
force_horkage_on(disable, ATA_HORKAGE_DISABLE),
};
static int __init ata_parse_force_one(char **cur,
struct ata_force_ent *force_ent,
const char **reason)
{
static const struct ata_force_param force_tbl[] __initconst = {
{ "40c", .cbl = ATA_CBL_PATA40 },
{ "80c", .cbl = ATA_CBL_PATA80 },
{ "short40c", .cbl = ATA_CBL_PATA40_SHORT },
{ "unk", .cbl = ATA_CBL_PATA_UNK },
{ "ign", .cbl = ATA_CBL_PATA_IGN },
{ "sata", .cbl = ATA_CBL_SATA },
{ "1.5Gbps", .spd_limit = 1 },
{ "3.0Gbps", .spd_limit = 2 },
{ "noncq", .horkage_on = ATA_HORKAGE_NONCQ },
{ "ncq", .horkage_off = ATA_HORKAGE_NONCQ },
{ "noncqtrim", .horkage_on = ATA_HORKAGE_NO_NCQ_TRIM },
{ "ncqtrim", .horkage_off = ATA_HORKAGE_NO_NCQ_TRIM },
{ "noncqati", .horkage_on = ATA_HORKAGE_NO_NCQ_ON_ATI },
{ "ncqati", .horkage_off = ATA_HORKAGE_NO_NCQ_ON_ATI },
{ "dump_id", .horkage_on = ATA_HORKAGE_DUMP_ID },
{ "pio0", .xfer_mask = 1 << (ATA_SHIFT_PIO + 0) },
{ "pio1", .xfer_mask = 1 << (ATA_SHIFT_PIO + 1) },
{ "pio2", .xfer_mask = 1 << (ATA_SHIFT_PIO + 2) },
{ "pio3", .xfer_mask = 1 << (ATA_SHIFT_PIO + 3) },
{ "pio4", .xfer_mask = 1 << (ATA_SHIFT_PIO + 4) },
{ "pio5", .xfer_mask = 1 << (ATA_SHIFT_PIO + 5) },
{ "pio6", .xfer_mask = 1 << (ATA_SHIFT_PIO + 6) },
{ "mwdma0", .xfer_mask = 1 << (ATA_SHIFT_MWDMA + 0) },
{ "mwdma1", .xfer_mask = 1 << (ATA_SHIFT_MWDMA + 1) },
{ "mwdma2", .xfer_mask = 1 << (ATA_SHIFT_MWDMA + 2) },
{ "mwdma3", .xfer_mask = 1 << (ATA_SHIFT_MWDMA + 3) },
{ "mwdma4", .xfer_mask = 1 << (ATA_SHIFT_MWDMA + 4) },
{ "udma0", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 0) },
{ "udma16", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 0) },
{ "udma/16", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 0) },
{ "udma1", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 1) },
{ "udma25", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 1) },
{ "udma/25", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 1) },
{ "udma2", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 2) },
{ "udma33", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 2) },
{ "udma/33", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 2) },
{ "udma3", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 3) },
{ "udma44", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 3) },
{ "udma/44", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 3) },
{ "udma4", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 4) },
{ "udma66", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 4) },
{ "udma/66", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 4) },
{ "udma5", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 5) },
{ "udma100", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 5) },
{ "udma/100", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 5) },
{ "udma6", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 6) },
{ "udma133", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 6) },
{ "udma/133", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 6) },
{ "udma7", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 7) },
{ "nohrst", .lflags = ATA_LFLAG_NO_HRST },
{ "nosrst", .lflags = ATA_LFLAG_NO_SRST },
{ "norst", .lflags = ATA_LFLAG_NO_HRST | ATA_LFLAG_NO_SRST },
{ "rstonce", .lflags = ATA_LFLAG_RST_ONCE },
{ "atapi_dmadir", .horkage_on = ATA_HORKAGE_ATAPI_DMADIR },
{ "disable", .horkage_on = ATA_HORKAGE_DISABLE },
};
char *start = *cur, *p = *cur;
char *id, *val, *endp;
const struct ata_force_param *match_fp = NULL;
@@ -6288,7 +6295,7 @@ static void __init ata_parse_force_param(void)
int last_port = -1, last_device = -1;
char *p, *cur, *next;
/* calculate maximum number of params and allocate force_tbl */
/* Calculate maximum number of params and allocate ata_force_tbl */
for (p = ata_force_param_buf; *p; p++)
if (*p == ',')
size++;

View File

@@ -1268,31 +1268,6 @@ int ata_sas_queuecmd(struct scsi_cmnd *cmd, struct ata_port *ap)
}
EXPORT_SYMBOL_GPL(ata_sas_queuecmd);
int ata_sas_allocate_tag(struct ata_port *ap)
{
unsigned int max_queue = ap->host->n_tags;
unsigned int i, tag;
for (i = 0, tag = ap->sas_last_tag + 1; i < max_queue; i++, tag++) {
tag = tag < max_queue ? tag : 0;
/* the last tag is reserved for internal command. */
if (ata_tag_internal(tag))
continue;
if (!test_and_set_bit(tag, &ap->sas_tag_allocated)) {
ap->sas_last_tag = tag;
return tag;
}
}
return -1;
}
void ata_sas_free_tag(unsigned int tag, struct ata_port *ap)
{
clear_bit(tag, &ap->sas_tag_allocated);
}
/**
* sata_async_notification - SATA async notification handler
* @ap: ATA port where async notification is received

View File

@@ -638,24 +638,48 @@ EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
static struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev,
struct scsi_cmnd *cmd)
{
struct ata_port *ap = dev->link->ap;
struct ata_queued_cmd *qc;
int tag;
qc = ata_qc_new_init(dev, scsi_cmd_to_rq(cmd)->tag);
if (qc) {
qc->scsicmd = cmd;
qc->scsidone = scsi_done;
if (unlikely(ap->pflags & ATA_PFLAG_FROZEN))
goto fail;
qc->sg = scsi_sglist(cmd);
qc->n_elem = scsi_sg_count(cmd);
if (scsi_cmd_to_rq(cmd)->rq_flags & RQF_QUIET)
qc->flags |= ATA_QCFLAG_QUIET;
if (ap->flags & ATA_FLAG_SAS_HOST) {
/*
* SAS hosts may queue > ATA_MAX_QUEUE commands so use
* unique per-device budget token as a tag.
*/
if (WARN_ON_ONCE(cmd->budget_token >= ATA_MAX_QUEUE))
goto fail;
tag = cmd->budget_token;
} else {
cmd->result = (DID_OK << 16) | SAM_STAT_TASK_SET_FULL;
scsi_done(cmd);
tag = scsi_cmd_to_rq(cmd)->tag;
}
qc = __ata_qc_from_tag(ap, tag);
qc->tag = qc->hw_tag = tag;
qc->ap = ap;
qc->dev = dev;
ata_qc_reinit(qc);
qc->scsicmd = cmd;
qc->scsidone = scsi_done;
qc->sg = scsi_sglist(cmd);
qc->n_elem = scsi_sg_count(cmd);
if (scsi_cmd_to_rq(cmd)->rq_flags & RQF_QUIET)
qc->flags |= ATA_QCFLAG_QUIET;
return qc;
fail:
set_host_byte(cmd, DID_OK);
set_status_byte(cmd, SAM_STAT_TASK_SET_FULL);
scsi_done(cmd);
return NULL;
}
static void ata_qc_set_pc_nbytes(struct ata_queued_cmd *qc)

View File

@@ -44,7 +44,6 @@ static inline void ata_force_cbl(struct ata_port *ap) { }
#endif
extern u64 ata_tf_to_lba(const struct ata_taskfile *tf);
extern u64 ata_tf_to_lba48(const struct ata_taskfile *tf);
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag);
extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
u64 block, u32 n_block, unsigned int tf_flags,
unsigned int tag, int class);
@@ -91,18 +90,6 @@ extern unsigned int ata_read_log_page(struct ata_device *dev, u8 log,
#define to_ata_port(d) container_of(d, struct ata_port, tdev)
/* libata-sata.c */
#ifdef CONFIG_SATA_HOST
int ata_sas_allocate_tag(struct ata_port *ap);
void ata_sas_free_tag(unsigned int tag, struct ata_port *ap);
#else
static inline int ata_sas_allocate_tag(struct ata_port *ap)
{
return -EOPNOTSUPP;
}
static inline void ata_sas_free_tag(unsigned int tag, struct ata_port *ap) { }
#endif
/* libata-acpi.c */
#ifdef CONFIG_ATA_ACPI
extern unsigned int ata_acpi_gtf_filter;

View File

@@ -536,8 +536,8 @@ static int pata_ftide010_probe(struct platform_device *pdev)
return 0;
err_dis_clk:
if (!IS_ERR(ftide->pclk))
clk_disable_unprepare(ftide->pclk);
clk_disable_unprepare(ftide->pclk);
return ret;
}
@@ -547,8 +547,7 @@ static int pata_ftide010_remove(struct platform_device *pdev)
struct ftide010 *ftide = host->private_data;
ata_host_detach(ftide->host);
if (!IS_ERR(ftide->pclk))
clk_disable_unprepare(ftide->pclk);
clk_disable_unprepare(ftide->pclk);
return 0;
}

View File

@@ -19,11 +19,12 @@
#include <linux/gfp.h>
#include <linux/delay.h>
#include <linux/libata.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/types.h>
#include <asm/cacheflush.h>
#include <asm/prom.h>
#include <asm/mpc52xx.h>
#include <linux/fsl/bestcomm/bestcomm.h>

View File

@@ -47,11 +47,9 @@
* criticial.
*/
static unsigned long sil680_selreg(struct ata_port *ap, int r)
static int sil680_selreg(struct ata_port *ap, int r)
{
unsigned long base = 0xA0 + r;
base += (ap->port_no << 4);
return base;
return 0xA0 + (ap->port_no << 4) + r;
}
/**
@@ -65,12 +63,9 @@ static unsigned long sil680_selreg(struct ata_port *ap, int r)
* the unit shift.
*/
static unsigned long sil680_seldev(struct ata_port *ap, struct ata_device *adev, int r)
static int sil680_seldev(struct ata_port *ap, struct ata_device *adev, int r)
{
unsigned long base = 0xA0 + r;
base += (ap->port_no << 4);
base |= adev->devno ? 2 : 0;
return base;
return 0xA0 + (ap->port_no << 4) + r + (adev->devno << 1);
}
@@ -85,8 +80,9 @@ static unsigned long sil680_seldev(struct ata_port *ap, struct ata_device *adev,
static int sil680_cable_detect(struct ata_port *ap)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
unsigned long addr = sil680_selreg(ap, 0);
int addr = sil680_selreg(ap, 0);
u8 ata66;
pci_read_config_byte(pdev, addr, &ata66);
if (ata66 & 1)
return ATA_CBL_PATA80;
@@ -113,9 +109,9 @@ static void sil680_set_piomode(struct ata_port *ap, struct ata_device *adev)
0x328A, 0x2283, 0x1281, 0x10C3, 0x10C1
};
unsigned long tfaddr = sil680_selreg(ap, 0x02);
unsigned long addr = sil680_seldev(ap, adev, 0x04);
unsigned long addr_mask = 0x80 + 4 * ap->port_no;
int tfaddr = sil680_selreg(ap, 0x02);
int addr = sil680_seldev(ap, adev, 0x04);
int addr_mask = 0x80 + 4 * ap->port_no;
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
int pio = adev->pio_mode - XFER_PIO_0;
int lowest_pio = pio;
@@ -165,9 +161,9 @@ static void sil680_set_dmamode(struct ata_port *ap, struct ata_device *adev)
static const u16 dma_table[3] = { 0x2208, 0x10C2, 0x10C1 };
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
unsigned long ma = sil680_seldev(ap, adev, 0x08);
unsigned long ua = sil680_seldev(ap, adev, 0x0C);
unsigned long addr_mask = 0x80 + 4 * ap->port_no;
int ma = sil680_seldev(ap, adev, 0x08);
int ua = sil680_seldev(ap, adev, 0x0C);
int addr_mask = 0x80 + 4 * ap->port_no;
int port_shift = adev->devno * 4;
u8 scsc, mode;
u16 multi, ultra;
@@ -219,7 +215,7 @@ static void sil680_sff_exec_command(struct ata_port *ap,
static bool sil680_sff_irq_check(struct ata_port *ap)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
unsigned long addr = sil680_selreg(ap, 1);
int addr = sil680_selreg(ap, 1);
u8 val;
pci_read_config_byte(pdev, addr, &val);

View File

@@ -248,9 +248,9 @@ static void via_do_set_mode(struct ata_port *ap, struct ata_device *adev,
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
struct ata_device *peer = ata_dev_pair(adev);
struct ata_timing t, p;
static int via_clock = 33333; /* Bus clock in kHZ */
unsigned long T = 1000000000 / via_clock;
unsigned long UT = T;
const int via_clock = 33333; /* Bus clock in kHz */
const int T = 1000000000 / via_clock;
int UT = T;
int ut;
int offset = 3 - (2*ap->port_no) - adev->devno;

View File

@@ -318,7 +318,6 @@ static int gemini_sata_probe(struct platform_device *pdev)
struct device_node *np = dev->of_node;
struct sata_gemini *sg;
struct regmap *map;
struct resource *res;
enum gemini_muxmode muxmode;
u32 gmode;
u32 gmask;
@@ -329,11 +328,7 @@ static int gemini_sata_probe(struct platform_device *pdev)
return -ENOMEM;
sg->dev = dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;
sg->base = devm_ioremap_resource(dev, res);
sg->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(sg->base))
return PTR_ERR(sg->base);

View File

@@ -3,4 +3,4 @@ ccflags-y += -I$(src)
obj-$(CONFIG_ZONEFS_FS) += zonefs.o
zonefs-y := super.o
zonefs-y := super.o sysfs.o

View File

@@ -27,6 +27,39 @@
#define CREATE_TRACE_POINTS
#include "trace.h"
/*
* Manage the active zone count. Called with zi->i_truncate_mutex held.
*/
static void zonefs_account_active(struct inode *inode)
{
struct zonefs_sb_info *sbi = ZONEFS_SB(inode->i_sb);
struct zonefs_inode_info *zi = ZONEFS_I(inode);
lockdep_assert_held(&zi->i_truncate_mutex);
if (zi->i_ztype != ZONEFS_ZTYPE_SEQ)
return;
/*
* If the zone is active, that is, if it is explicitly open or
* partially written, check if it was already accounted as active.
*/
if ((zi->i_flags & ZONEFS_ZONE_OPEN) ||
(zi->i_wpoffset > 0 && zi->i_wpoffset < zi->i_max_size)) {
if (!(zi->i_flags & ZONEFS_ZONE_ACTIVE)) {
zi->i_flags |= ZONEFS_ZONE_ACTIVE;
atomic_inc(&sbi->s_active_seq_files);
}
return;
}
/* The zone is not active. If it was, update the active count */
if (zi->i_flags & ZONEFS_ZONE_ACTIVE) {
zi->i_flags &= ~ZONEFS_ZONE_ACTIVE;
atomic_dec(&sbi->s_active_seq_files);
}
}
static inline int zonefs_zone_mgmt(struct inode *inode,
enum req_opf op)
{
@@ -68,8 +101,13 @@ static inline void zonefs_i_size_write(struct inode *inode, loff_t isize)
* A full zone is no longer open/active and does not need
* explicit closing.
*/
if (isize >= zi->i_max_size)
zi->i_flags &= ~ZONEFS_ZONE_OPEN;
if (isize >= zi->i_max_size) {
struct zonefs_sb_info *sbi = ZONEFS_SB(inode->i_sb);
if (zi->i_flags & ZONEFS_ZONE_ACTIVE)
atomic_dec(&sbi->s_active_seq_files);
zi->i_flags &= ~(ZONEFS_ZONE_OPEN | ZONEFS_ZONE_ACTIVE);
}
}
static int zonefs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
@@ -397,6 +435,7 @@ static int zonefs_io_error_cb(struct blk_zone *zone, unsigned int idx,
zonefs_update_stats(inode, data_size);
zonefs_i_size_write(inode, data_size);
zi->i_wpoffset = data_size;
zonefs_account_active(inode);
return 0;
}
@@ -508,6 +547,7 @@ static int zonefs_file_truncate(struct inode *inode, loff_t isize)
zonefs_update_stats(inode, isize);
truncate_setsize(inode, isize);
zi->i_wpoffset = isize;
zonefs_account_active(inode);
unlock:
mutex_unlock(&zi->i_truncate_mutex);
@@ -865,8 +905,15 @@ static ssize_t zonefs_file_dio_write(struct kiocb *iocb, struct iov_iter *from)
(ret > 0 || ret == -EIOCBQUEUED)) {
if (ret > 0)
count = ret;
/*
* Update the zone write pointer offset assuming the write
* operation succeeded. If it did not, the error recovery path
* will correct it. Also do active seq file accounting.
*/
mutex_lock(&zi->i_truncate_mutex);
zi->i_wpoffset += count;
zonefs_account_active(inode);
mutex_unlock(&zi->i_truncate_mutex);
}
@@ -1008,13 +1055,13 @@ inode_unlock:
return ret;
}
static inline bool zonefs_file_use_exp_open(struct inode *inode, struct file *file)
/*
* Write open accounting is done only for sequential files.
*/
static inline bool zonefs_seq_file_need_wro(struct inode *inode,
struct file *file)
{
struct zonefs_inode_info *zi = ZONEFS_I(inode);
struct zonefs_sb_info *sbi = ZONEFS_SB(inode->i_sb);
if (!(sbi->s_mount_opts & ZONEFS_MNTOPT_EXPLICIT_OPEN))
return false;
if (zi->i_ztype != ZONEFS_ZTYPE_SEQ)
return false;
@@ -1025,28 +1072,34 @@ static inline bool zonefs_file_use_exp_open(struct inode *inode, struct file *fi
return true;
}
static int zonefs_open_zone(struct inode *inode)
static int zonefs_seq_file_write_open(struct inode *inode)
{
struct zonefs_inode_info *zi = ZONEFS_I(inode);
struct zonefs_sb_info *sbi = ZONEFS_SB(inode->i_sb);
int ret = 0;
mutex_lock(&zi->i_truncate_mutex);
if (!zi->i_wr_refcnt) {
if (atomic_inc_return(&sbi->s_open_zones) > sbi->s_max_open_zones) {
atomic_dec(&sbi->s_open_zones);
ret = -EBUSY;
goto unlock;
}
struct zonefs_sb_info *sbi = ZONEFS_SB(inode->i_sb);
unsigned int wro = atomic_inc_return(&sbi->s_wro_seq_files);
if (i_size_read(inode) < zi->i_max_size) {
ret = zonefs_zone_mgmt(inode, REQ_OP_ZONE_OPEN);
if (ret) {
atomic_dec(&sbi->s_open_zones);
if (sbi->s_mount_opts & ZONEFS_MNTOPT_EXPLICIT_OPEN) {
if (wro > sbi->s_max_wro_seq_files) {
atomic_dec(&sbi->s_wro_seq_files);
ret = -EBUSY;
goto unlock;
}
zi->i_flags |= ZONEFS_ZONE_OPEN;
if (i_size_read(inode) < zi->i_max_size) {
ret = zonefs_zone_mgmt(inode, REQ_OP_ZONE_OPEN);
if (ret) {
atomic_dec(&sbi->s_wro_seq_files);
goto unlock;
}
zi->i_flags |= ZONEFS_ZONE_OPEN;
zonefs_account_active(inode);
}
}
}
@@ -1066,30 +1119,31 @@ static int zonefs_file_open(struct inode *inode, struct file *file)
if (ret)
return ret;
if (zonefs_file_use_exp_open(inode, file))
return zonefs_open_zone(inode);
if (zonefs_seq_file_need_wro(inode, file))
return zonefs_seq_file_write_open(inode);
return 0;
}
static void zonefs_close_zone(struct inode *inode)
static void zonefs_seq_file_write_close(struct inode *inode)
{
struct zonefs_inode_info *zi = ZONEFS_I(inode);
struct super_block *sb = inode->i_sb;
struct zonefs_sb_info *sbi = ZONEFS_SB(sb);
int ret = 0;
mutex_lock(&zi->i_truncate_mutex);
zi->i_wr_refcnt--;
if (!zi->i_wr_refcnt) {
struct zonefs_sb_info *sbi = ZONEFS_SB(inode->i_sb);
struct super_block *sb = inode->i_sb;
/*
* If the file zone is full, it is not open anymore and we only
* need to decrement the open count.
*/
if (!(zi->i_flags & ZONEFS_ZONE_OPEN))
goto dec;
if (zi->i_wr_refcnt)
goto unlock;
/*
* The file zone may not be open anymore (e.g. the file was truncated to
* its maximum size or it was fully written). For this case, we only
* need to decrement the write open count.
*/
if (zi->i_flags & ZONEFS_ZONE_OPEN) {
ret = zonefs_zone_mgmt(inode, REQ_OP_ZONE_CLOSE);
if (ret) {
__zonefs_io_error(inode, false);
@@ -1101,14 +1155,23 @@ static void zonefs_close_zone(struct inode *inode)
*/
if (zi->i_flags & ZONEFS_ZONE_OPEN &&
!(sb->s_flags & SB_RDONLY)) {
zonefs_warn(sb, "closing zone failed, remounting filesystem read-only\n");
zonefs_warn(sb,
"closing zone at %llu failed %d\n",
zi->i_zsector, ret);
zonefs_warn(sb,
"remounting filesystem read-only\n");
sb->s_flags |= SB_RDONLY;
}
goto unlock;
}
zi->i_flags &= ~ZONEFS_ZONE_OPEN;
dec:
atomic_dec(&sbi->s_open_zones);
zonefs_account_active(inode);
}
atomic_dec(&sbi->s_wro_seq_files);
unlock:
mutex_unlock(&zi->i_truncate_mutex);
}
@@ -1120,8 +1183,8 @@ static int zonefs_file_release(struct inode *inode, struct file *file)
* the zone has gone offline or read-only). Make sure we don't fail the
* close(2) for user-space.
*/
if (zonefs_file_use_exp_open(inode, file))
zonefs_close_zone(inode);
if (zonefs_seq_file_need_wro(inode, file))
zonefs_seq_file_write_close(inode);
return 0;
}
@@ -1310,7 +1373,7 @@ static int zonefs_init_file_inode(struct inode *inode, struct blk_zone *zone,
struct super_block *sb = inode->i_sb;
struct zonefs_sb_info *sbi = ZONEFS_SB(sb);
struct zonefs_inode_info *zi = ZONEFS_I(inode);
int ret = 0;
int ret;
inode->i_ino = zone->start >> sbi->s_zone_sectors_shift;
inode->i_mode = S_IFREG | sbi->s_perm;
@@ -1336,6 +1399,8 @@ static int zonefs_init_file_inode(struct inode *inode, struct blk_zone *zone,
sbi->s_blocks += zi->i_max_size >> sb->s_blocksize_bits;
sbi->s_used_blocks += zi->i_wpoffset >> sb->s_blocksize_bits;
mutex_lock(&zi->i_truncate_mutex);
/*
* For sequential zones, make sure that any open zone is closed first
* to ensure that the initial number of open zones is 0, in sync with
@@ -1345,12 +1410,17 @@ static int zonefs_init_file_inode(struct inode *inode, struct blk_zone *zone,
if (type == ZONEFS_ZTYPE_SEQ &&
(zone->cond == BLK_ZONE_COND_IMP_OPEN ||
zone->cond == BLK_ZONE_COND_EXP_OPEN)) {
mutex_lock(&zi->i_truncate_mutex);
ret = zonefs_zone_mgmt(inode, REQ_OP_ZONE_CLOSE);
mutex_unlock(&zi->i_truncate_mutex);
if (ret)
goto unlock;
}
return ret;
zonefs_account_active(inode);
unlock:
mutex_unlock(&zi->i_truncate_mutex);
return 0;
}
static struct dentry *zonefs_create_inode(struct dentry *parent,
@@ -1687,14 +1757,18 @@ static int zonefs_fill_super(struct super_block *sb, void *data, int silent)
sbi->s_gid = GLOBAL_ROOT_GID;
sbi->s_perm = 0640;
sbi->s_mount_opts = ZONEFS_MNTOPT_ERRORS_RO;
sbi->s_max_open_zones = bdev_max_open_zones(sb->s_bdev);
atomic_set(&sbi->s_open_zones, 0);
if (!sbi->s_max_open_zones &&
atomic_set(&sbi->s_wro_seq_files, 0);
sbi->s_max_wro_seq_files = bdev_max_open_zones(sb->s_bdev);
if (!sbi->s_max_wro_seq_files &&
sbi->s_mount_opts & ZONEFS_MNTOPT_EXPLICIT_OPEN) {
zonefs_info(sb, "No open zones limit. Ignoring explicit_open mount option\n");
sbi->s_mount_opts &= ~ZONEFS_MNTOPT_EXPLICIT_OPEN;
}
atomic_set(&sbi->s_active_seq_files, 0);
sbi->s_max_active_seq_files = bdev_max_active_zones(sb->s_bdev);
ret = zonefs_read_super(sb);
if (ret)
return ret;
@@ -1709,6 +1783,10 @@ static int zonefs_fill_super(struct super_block *sb, void *data, int silent)
if (ret)
goto cleanup;
ret = zonefs_sysfs_register(sb);
if (ret)
goto cleanup;
zonefs_info(sb, "Mounting %u zones",
blkdev_nr_zones(sb->s_bdev->bd_disk));
@@ -1754,6 +1832,8 @@ static void zonefs_kill_super(struct super_block *sb)
if (sb->s_root)
d_genocide(sb->s_root);
zonefs_sysfs_unregister(sb);
kill_block_super(sb);
kfree(sbi);
}
@@ -1801,16 +1881,26 @@ static int __init zonefs_init(void)
return ret;
ret = register_filesystem(&zonefs_type);
if (ret) {
zonefs_destroy_inodecache();
return ret;
}
if (ret)
goto destroy_inodecache;
ret = zonefs_sysfs_init();
if (ret)
goto unregister_fs;
return 0;
unregister_fs:
unregister_filesystem(&zonefs_type);
destroy_inodecache:
zonefs_destroy_inodecache();
return ret;
}
static void __exit zonefs_exit(void)
{
zonefs_sysfs_exit();
zonefs_destroy_inodecache();
unregister_filesystem(&zonefs_type);
}

139
fs/zonefs/sysfs.c Normal file
View File

@@ -0,0 +1,139 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Simple file system for zoned block devices exposing zones as files.
*
* Copyright (C) 2022 Western Digital Corporation or its affiliates.
*/
#include <linux/fs.h>
#include <linux/seq_file.h>
#include <linux/blkdev.h>
#include "zonefs.h"
struct zonefs_sysfs_attr {
struct attribute attr;
ssize_t (*show)(struct zonefs_sb_info *sbi, char *buf);
};
static inline struct zonefs_sysfs_attr *to_attr(struct attribute *attr)
{
return container_of(attr, struct zonefs_sysfs_attr, attr);
}
#define ZONEFS_SYSFS_ATTR_RO(name) \
static struct zonefs_sysfs_attr zonefs_sysfs_attr_##name = __ATTR_RO(name)
#define ATTR_LIST(name) &zonefs_sysfs_attr_##name.attr
static ssize_t zonefs_sysfs_attr_show(struct kobject *kobj,
struct attribute *attr, char *buf)
{
struct zonefs_sb_info *sbi =
container_of(kobj, struct zonefs_sb_info, s_kobj);
struct zonefs_sysfs_attr *zonefs_attr =
container_of(attr, struct zonefs_sysfs_attr, attr);
if (!zonefs_attr->show)
return 0;
return zonefs_attr->show(sbi, buf);
}
static ssize_t max_wro_seq_files_show(struct zonefs_sb_info *sbi, char *buf)
{
return sysfs_emit(buf, "%u\n", sbi->s_max_wro_seq_files);
}
ZONEFS_SYSFS_ATTR_RO(max_wro_seq_files);
static ssize_t nr_wro_seq_files_show(struct zonefs_sb_info *sbi, char *buf)
{
return sysfs_emit(buf, "%d\n", atomic_read(&sbi->s_wro_seq_files));
}
ZONEFS_SYSFS_ATTR_RO(nr_wro_seq_files);
static ssize_t max_active_seq_files_show(struct zonefs_sb_info *sbi, char *buf)
{
return sysfs_emit(buf, "%u\n", sbi->s_max_active_seq_files);
}
ZONEFS_SYSFS_ATTR_RO(max_active_seq_files);
static ssize_t nr_active_seq_files_show(struct zonefs_sb_info *sbi, char *buf)
{
return sysfs_emit(buf, "%d\n", atomic_read(&sbi->s_active_seq_files));
}
ZONEFS_SYSFS_ATTR_RO(nr_active_seq_files);
static struct attribute *zonefs_sysfs_attrs[] = {
ATTR_LIST(max_wro_seq_files),
ATTR_LIST(nr_wro_seq_files),
ATTR_LIST(max_active_seq_files),
ATTR_LIST(nr_active_seq_files),
NULL,
};
ATTRIBUTE_GROUPS(zonefs_sysfs);
static void zonefs_sysfs_sb_release(struct kobject *kobj)
{
struct zonefs_sb_info *sbi =
container_of(kobj, struct zonefs_sb_info, s_kobj);
complete(&sbi->s_kobj_unregister);
}
static const struct sysfs_ops zonefs_sysfs_attr_ops = {
.show = zonefs_sysfs_attr_show,
};
static struct kobj_type zonefs_sb_ktype = {
.default_groups = zonefs_sysfs_groups,
.sysfs_ops = &zonefs_sysfs_attr_ops,
.release = zonefs_sysfs_sb_release,
};
static struct kobject *zonefs_sysfs_root;
int zonefs_sysfs_register(struct super_block *sb)
{
struct zonefs_sb_info *sbi = ZONEFS_SB(sb);
int ret;
init_completion(&sbi->s_kobj_unregister);
ret = kobject_init_and_add(&sbi->s_kobj, &zonefs_sb_ktype,
zonefs_sysfs_root, "%s", sb->s_id);
if (ret) {
kobject_put(&sbi->s_kobj);
wait_for_completion(&sbi->s_kobj_unregister);
return ret;
}
sbi->s_sysfs_registered = true;
return 0;
}
void zonefs_sysfs_unregister(struct super_block *sb)
{
struct zonefs_sb_info *sbi = ZONEFS_SB(sb);
if (!sbi || !sbi->s_sysfs_registered)
return;
kobject_del(&sbi->s_kobj);
kobject_put(&sbi->s_kobj);
wait_for_completion(&sbi->s_kobj_unregister);
}
int __init zonefs_sysfs_init(void)
{
zonefs_sysfs_root = kobject_create_and_add("zonefs", fs_kobj);
if (!zonefs_sysfs_root)
return -ENOMEM;
return 0;
}
void zonefs_sysfs_exit(void)
{
kobject_put(zonefs_sysfs_root);
zonefs_sysfs_root = NULL;
}

View File

@@ -12,6 +12,7 @@
#include <linux/uuid.h>
#include <linux/mutex.h>
#include <linux/rwsem.h>
#include <linux/kobject.h>
/*
* Maximum length of file names: this only needs to be large enough to fit
@@ -39,6 +40,7 @@ static inline enum zonefs_ztype zonefs_zone_type(struct blk_zone *zone)
}
#define ZONEFS_ZONE_OPEN (1 << 0)
#define ZONEFS_ZONE_ACTIVE (1 << 1)
/*
* In-memory inode data.
@@ -182,8 +184,15 @@ struct zonefs_sb_info {
loff_t s_blocks;
loff_t s_used_blocks;
unsigned int s_max_open_zones;
atomic_t s_open_zones;
unsigned int s_max_wro_seq_files;
atomic_t s_wro_seq_files;
unsigned int s_max_active_seq_files;
atomic_t s_active_seq_files;
bool s_sysfs_registered;
struct kobject s_kobj;
struct completion s_kobj_unregister;
};
static inline struct zonefs_sb_info *ZONEFS_SB(struct super_block *sb)
@@ -198,4 +207,9 @@ static inline struct zonefs_sb_info *ZONEFS_SB(struct super_block *sb)
#define zonefs_warn(sb, format, args...) \
pr_warn("zonefs (%s) WARNING: " format, sb->s_id, ## args)
int zonefs_sysfs_register(struct super_block *sb);
void zonefs_sysfs_unregister(struct super_block *sb);
int zonefs_sysfs_init(void);
void zonefs_sysfs_exit(void);
#endif

View File

@@ -820,7 +820,6 @@ struct ata_port {
unsigned int cbl; /* cable type; ATA_CBL_xxx */
struct ata_queued_cmd qcmd[ATA_MAX_QUEUE + 1];
unsigned long sas_tag_allocated; /* for sas tag allocation only */
u64 qc_active;
int nr_active_links; /* #links with active qcs */
unsigned int sas_last_tag; /* track next tag hw expects */
@@ -1111,7 +1110,7 @@ extern void ata_unpack_xfermask(unsigned long xfer_mask,
unsigned long *udma_mask);
extern u8 ata_xfer_mask2mode(unsigned long xfer_mask);
extern unsigned long ata_xfer_mode2mask(u8 xfer_mode);
extern int ata_xfer_mode2shift(unsigned long xfer_mode);
extern int ata_xfer_mode2shift(u8 xfer_mode);
extern const char *ata_mode_string(unsigned long xfer_mask);
extern unsigned long ata_id_xfermask(const u16 *id);
extern int ata_std_qc_defer(struct ata_queued_cmd *qc);

View File

@@ -1,11 +1,8 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Generic infrastructure for lifetime debugging of objects.
*
* Started by Thomas Gleixner
*
* Copyright (C) 2008, Thomas Gleixner <tglx@linutronix.de>
*
* For licencing details see kernel-base/COPYING
*/
#define pr_fmt(fmt) "ODEBUG: " fmt

View File

@@ -188,14 +188,18 @@ EXPORT_SYMBOL(irq_poll_init);
static int irq_poll_cpu_dead(unsigned int cpu)
{
/*
* If a CPU goes away, splice its entries to the current CPU
* and trigger a run of the softirq
* If a CPU goes away, splice its entries to the current CPU and
* set the POLL softirq bit. The local_bh_disable()/enable() pair
* ensures that it is handled. Otherwise the current CPU could
* reach idle with the POLL softirq pending.
*/
local_bh_disable();
local_irq_disable();
list_splice_init(&per_cpu(blk_cpu_iopoll, cpu),
this_cpu_ptr(&blk_cpu_iopoll));
__raise_softirq_irqoff(IRQ_POLL_SOFTIRQ);
local_irq_enable();
local_bh_enable();
return 0;
}