--- /dev/null
+From 2f73cabdcf83fc53ea05deace13a531bc515c2f8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Aug 2020 17:49:00 +0200
+Subject: affs: fix basic permission bits to actually work
+
+From: Max Staudt <max@enpas.org>
+
+[ Upstream commit d3a84a8d0dde4e26bc084b36ffcbdc5932ac85e2 ]
+
+The basic permission bits (protection bits in AmigaOS) have been broken
+in Linux' AFFS - it would only set bits, but never delete them.
+Also, contrary to the documentation, the Archived bit was not handled.
+
+Let's fix this for good, and set the bits such that Linux and classic
+AmigaOS can coexist in the most peaceful manner.
+
+Also, update the documentation to represent the current state of things.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable@vger.kernel.org
+Signed-off-by: Max Staudt <max@enpas.org>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/filesystems/affs.txt | 16 ++++++++++------
+ fs/affs/amigaffs.c | 27 +++++++++++++++++++++++++++
+ fs/affs/file.c | 26 +++++++++++++++++++++++++-
+ 3 files changed, 62 insertions(+), 7 deletions(-)
+
+diff --git a/Documentation/filesystems/affs.txt b/Documentation/filesystems/affs.txt
+index 71b63c2b98410..a8f1a58e36922 100644
+--- a/Documentation/filesystems/affs.txt
++++ b/Documentation/filesystems/affs.txt
+@@ -93,13 +93,15 @@ The Amiga protection flags RWEDRWEDHSPARWED are handled as follows:
+
+ - R maps to r for user, group and others. On directories, R implies x.
+
+- - If both W and D are allowed, w will be set.
++ - W maps to w.
+
+ - E maps to x.
+
+- - H and P are always retained and ignored under Linux.
++ - D is ignored.
+
+- - A is always reset when a file is written to.
++ - H, S and P are always retained and ignored under Linux.
++
++ - A is cleared when a file is written to.
+
+ User id and group id will be used unless set[gu]id are given as mount
+ options. Since most of the Amiga file systems are single user systems
+@@ -111,11 +113,13 @@ Linux -> Amiga:
+
+ The Linux rwxrwxrwx file mode is handled as follows:
+
+- - r permission will set R for user, group and others.
++ - r permission will allow R for user, group and others.
++
++ - w permission will allow W for user, group and others.
+
+- - w permission will set W and D for user, group and others.
++ - x permission of the user will allow E for plain files.
+
+- - x permission of the user will set E for plain files.
++ - D will be allowed for user, group and others.
+
+ - All other flags (suid, sgid, ...) are ignored and will
+ not be retained.
+diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c
+index fd7a7542956d9..e57f12317ab62 100644
+--- a/fs/affs/amigaffs.c
++++ b/fs/affs/amigaffs.c
+@@ -418,24 +418,51 @@ mode_to_prot(struct inode *inode)
+ u32 prot = AFFS_I(inode)->i_protect;
+ umode_t mode = inode->i_mode;
+
++ /*
++ * First, clear all RWED bits for owner, group, other.
++ * Then, recalculate them afresh.
++ *
++ * We'll always clear the delete-inhibit bit for the owner, as that is
++ * the classic single-user mode AmigaOS protection bit and we need to
++ * stay compatible with all scenarios.
++ *
++ * Since multi-user AmigaOS is an extension, we'll only set the
++ * delete-allow bit if any of the other bits in the same user class
++ * (group/other) are used.
++ */
++ prot &= ~(FIBF_NOEXECUTE | FIBF_NOREAD
++ | FIBF_NOWRITE | FIBF_NODELETE
++ | FIBF_GRP_EXECUTE | FIBF_GRP_READ
++ | FIBF_GRP_WRITE | FIBF_GRP_DELETE
++ | FIBF_OTR_EXECUTE | FIBF_OTR_READ
++ | FIBF_OTR_WRITE | FIBF_OTR_DELETE);
++
++ /* Classic single-user AmigaOS flags. These are inverted. */
+ if (!(mode & 0100))
+ prot |= FIBF_NOEXECUTE;
+ if (!(mode & 0400))
+ prot |= FIBF_NOREAD;
+ if (!(mode & 0200))
+ prot |= FIBF_NOWRITE;
++
++ /* Multi-user extended flags. Not inverted. */
+ if (mode & 0010)
+ prot |= FIBF_GRP_EXECUTE;
+ if (mode & 0040)
+ prot |= FIBF_GRP_READ;
+ if (mode & 0020)
+ prot |= FIBF_GRP_WRITE;
++ if (mode & 0070)
++ prot |= FIBF_GRP_DELETE;
++
+ if (mode & 0001)
+ prot |= FIBF_OTR_EXECUTE;
+ if (mode & 0004)
+ prot |= FIBF_OTR_READ;
+ if (mode & 0002)
+ prot |= FIBF_OTR_WRITE;
++ if (mode & 0007)
++ prot |= FIBF_OTR_DELETE;
+
+ AFFS_I(inode)->i_protect = prot;
+ }
+diff --git a/fs/affs/file.c b/fs/affs/file.c
+index 0deec9cc2362c..0daca9d00cd8b 100644
+--- a/fs/affs/file.c
++++ b/fs/affs/file.c
+@@ -427,6 +427,24 @@ static int affs_write_begin(struct file *file, struct address_space *mapping,
+ return ret;
+ }
+
++static int affs_write_end(struct file *file, struct address_space *mapping,
++ loff_t pos, unsigned int len, unsigned int copied,
++ struct page *page, void *fsdata)
++{
++ struct inode *inode = mapping->host;
++ int ret;
++
++ ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
++
++ /* Clear Archived bit on file writes, as AmigaOS would do */
++ if (AFFS_I(inode)->i_protect & FIBF_ARCHIVED) {
++ AFFS_I(inode)->i_protect &= ~FIBF_ARCHIVED;
++ mark_inode_dirty(inode);
++ }
++
++ return ret;
++}
++
+ static sector_t _affs_bmap(struct address_space *mapping, sector_t block)
+ {
+ return generic_block_bmap(mapping,block,affs_get_block);
+@@ -436,7 +454,7 @@ const struct address_space_operations affs_aops = {
+ .readpage = affs_readpage,
+ .writepage = affs_writepage,
+ .write_begin = affs_write_begin,
+- .write_end = generic_write_end,
++ .write_end = affs_write_end,
+ .direct_IO = affs_direct_IO,
+ .bmap = _affs_bmap
+ };
+@@ -793,6 +811,12 @@ done:
+ if (tmp > inode->i_size)
+ inode->i_size = AFFS_I(inode)->mmu_private = tmp;
+
++ /* Clear Archived bit on file writes, as AmigaOS would do */
++ if (AFFS_I(inode)->i_protect & FIBF_ARCHIVED) {
++ AFFS_I(inode)->i_protect &= ~FIBF_ARCHIVED;
++ mark_inode_dirty(inode);
++ }
++
+ err_first_bh:
+ unlock_page(page);
+ put_page(page);
+--
+2.25.1
+
--- /dev/null
+From ee1bac1e54c8e02ee15fa1fadea4f47c96d36fe5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 23 Aug 2020 16:55:37 +0900
+Subject: ALSA; firewire-tascam: exclude Tascam FE-8 from detection
+
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+
+Tascam FE-8 is known to support communication by asynchronous transaction
+only. The support can be implemented in userspace application and
+snd-firewire-ctl-services project has the support. However, ALSA
+firewire-tascam driver is bound to the model.
+
+This commit changes device entries so that the model is excluded. In a
+commit 53b3ffee7885 ("ALSA: firewire-tascam: change device probing
+processing"), I addressed to the concern that version field in
+configuration differs depending on installed firmware. However, as long
+as I checked, the version number is fixed. It's safe to return version
+number back to modalias.
+
+Fixes: 53b3ffee7885 ("ALSA: firewire-tascam: change device probing processing")
+Cc: <stable@vger.kernel.org> # 4.4+
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Link: https://lore.kernel.org/r/20200823075537.56255-1-o-takashi@sakamocchi.jp
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+---
+ sound/firewire/tascam/tascam.c | 30 +++++++++++++++++++++++++++++-
+ 1 file changed, 29 insertions(+), 1 deletion(-)
+
+diff --git a/sound/firewire/tascam/tascam.c b/sound/firewire/tascam/tascam.c
+index 4c967ac1c0e83..40ed4c92e48bd 100644
+--- a/sound/firewire/tascam/tascam.c
++++ b/sound/firewire/tascam/tascam.c
+@@ -225,11 +225,39 @@ static void snd_tscm_remove(struct fw_unit *unit)
+ }
+
+ static const struct ieee1394_device_id snd_tscm_id_table[] = {
++ // Tascam, FW-1884.
+ {
+ .match_flags = IEEE1394_MATCH_VENDOR_ID |
+- IEEE1394_MATCH_SPECIFIER_ID,
++ IEEE1394_MATCH_SPECIFIER_ID |
++ IEEE1394_MATCH_VERSION,
+ .vendor_id = 0x00022e,
+ .specifier_id = 0x00022e,
++ .version = 0x800000,
++ },
++ // Tascam, FE-8 (.version = 0x800001)
++ // This kernel module doesn't support FE-8 because the most of features
++ // can be implemented in userspace without any specific support of this
++ // module.
++ //
++ // .version = 0x800002 is unknown.
++ //
++ // Tascam, FW-1082.
++ {
++ .match_flags = IEEE1394_MATCH_VENDOR_ID |
++ IEEE1394_MATCH_SPECIFIER_ID |
++ IEEE1394_MATCH_VERSION,
++ .vendor_id = 0x00022e,
++ .specifier_id = 0x00022e,
++ .version = 0x800003,
++ },
++ // Tascam, FW-1804.
++ {
++ .match_flags = IEEE1394_MATCH_VENDOR_ID |
++ IEEE1394_MATCH_SPECIFIER_ID |
++ IEEE1394_MATCH_VERSION,
++ .vendor_id = 0x00022e,
++ .specifier_id = 0x00022e,
++ .version = 0x800004,
+ },
+ /* FE-08 requires reverse-engineering because it just has faders. */
+ {}
+--
+2.25.1
+
--- /dev/null
+From 37d0c765f35003c51c84c1ddbd0c88d6ee7e4ae3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Feb 2017 14:27:52 -0800
+Subject: fs/affs: use octal for permissions
+
+From: Fabian Frederick <fabf@skynet.be>
+
+[ Upstream commit 1bafd6f164d9ec9bf2fa9829051fbeb36342be0b ]
+
+According to commit f90774e1fd27 ("checkpatch: look for symbolic
+permissions and suggest octal instead")
+
+Link: http://lkml.kernel.org/r/20170109191208.6085-5-fabf@skynet.be
+Signed-off-by: Fabian Frederick <fabf@skynet.be>
+Cc: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/affs/amigaffs.c | 36 ++++++++++++++++++------------------
+ 1 file changed, 18 insertions(+), 18 deletions(-)
+
+diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c
+index 0ec65c133b934..fd7a7542956d9 100644
+--- a/fs/affs/amigaffs.c
++++ b/fs/affs/amigaffs.c
+@@ -391,23 +391,23 @@ prot_to_mode(u32 prot)
+ umode_t mode = 0;
+
+ if (!(prot & FIBF_NOWRITE))
+- mode |= S_IWUSR;
++ mode |= 0200;
+ if (!(prot & FIBF_NOREAD))
+- mode |= S_IRUSR;
++ mode |= 0400;
+ if (!(prot & FIBF_NOEXECUTE))
+- mode |= S_IXUSR;
++ mode |= 0100;
+ if (prot & FIBF_GRP_WRITE)
+- mode |= S_IWGRP;
++ mode |= 0020;
+ if (prot & FIBF_GRP_READ)
+- mode |= S_IRGRP;
++ mode |= 0040;
+ if (prot & FIBF_GRP_EXECUTE)
+- mode |= S_IXGRP;
++ mode |= 0010;
+ if (prot & FIBF_OTR_WRITE)
+- mode |= S_IWOTH;
++ mode |= 0002;
+ if (prot & FIBF_OTR_READ)
+- mode |= S_IROTH;
++ mode |= 0004;
+ if (prot & FIBF_OTR_EXECUTE)
+- mode |= S_IXOTH;
++ mode |= 0001;
+
+ return mode;
+ }
+@@ -418,23 +418,23 @@ mode_to_prot(struct inode *inode)
+ u32 prot = AFFS_I(inode)->i_protect;
+ umode_t mode = inode->i_mode;
+
+- if (!(mode & S_IXUSR))
++ if (!(mode & 0100))
+ prot |= FIBF_NOEXECUTE;
+- if (!(mode & S_IRUSR))
++ if (!(mode & 0400))
+ prot |= FIBF_NOREAD;
+- if (!(mode & S_IWUSR))
++ if (!(mode & 0200))
+ prot |= FIBF_NOWRITE;
+- if (mode & S_IXGRP)
++ if (mode & 0010)
+ prot |= FIBF_GRP_EXECUTE;
+- if (mode & S_IRGRP)
++ if (mode & 0040)
+ prot |= FIBF_GRP_READ;
+- if (mode & S_IWGRP)
++ if (mode & 0020)
+ prot |= FIBF_GRP_WRITE;
+- if (mode & S_IXOTH)
++ if (mode & 0001)
+ prot |= FIBF_OTR_EXECUTE;
+- if (mode & S_IROTH)
++ if (mode & 0004)
+ prot |= FIBF_OTR_READ;
+- if (mode & S_IWOTH)
++ if (mode & 0002)
+ prot |= FIBF_OTR_WRITE;
+
+ AFFS_I(inode)->i_protect = prot;
+--
+2.25.1
+