From 955999c9023290da18230b57df1f04187a43a4c0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 27 Nov 2017 09:02:22 +0100 Subject: [PATCH 01/17] m68k/defconfig: Update defconfigs for v4.15-rc1 Signed-off-by: Geert Uytterhoeven --- arch/m68k/configs/amiga_defconfig | 4 +++- arch/m68k/configs/apollo_defconfig | 4 +++- arch/m68k/configs/atari_defconfig | 4 +++- arch/m68k/configs/bvme6000_defconfig | 4 +++- arch/m68k/configs/hp300_defconfig | 4 +++- arch/m68k/configs/mac_defconfig | 4 +++- arch/m68k/configs/multi_defconfig | 4 +++- arch/m68k/configs/mvme147_defconfig | 4 +++- arch/m68k/configs/mvme16x_defconfig | 4 +++- arch/m68k/configs/q40_defconfig | 4 +++- arch/m68k/configs/sun3_defconfig | 4 +++- arch/m68k/configs/sun3x_defconfig | 4 +++- 12 files changed, 36 insertions(+), 12 deletions(-) diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig index 5b5fa9831b4d..e0b285e1e75f 100644 --- a/arch/m68k/configs/amiga_defconfig +++ b/arch/m68k/configs/amiga_defconfig @@ -454,7 +454,6 @@ CONFIG_PPS_CLIENT_LDISC=m CONFIG_PPS_CLIENT_PARPORT=m CONFIG_PTP_1588_CLOCK=m # CONFIG_HWMON is not set -# CONFIG_RC_CORE is not set CONFIG_FB=y CONFIG_FB_CIRRUS=y CONFIG_FB_AMIGA=y @@ -595,6 +594,7 @@ CONFIG_TEST_RHASHTABLE=m CONFIG_TEST_HASH=m CONFIG_TEST_USER_COPY=m CONFIG_TEST_BPF=m +CONFIG_TEST_FIND_BIT=m CONFIG_TEST_FIRMWARE=m CONFIG_TEST_SYSCTL=m CONFIG_TEST_UDELAY=m @@ -624,6 +624,7 @@ CONFIG_CRYPTO_RMD256=m CONFIG_CRYPTO_RMD320=m CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_SHA3=m +CONFIG_CRYPTO_SM3=m CONFIG_CRYPTO_TGR192=m CONFIG_CRYPTO_WP512=m CONFIG_CRYPTO_AES_TI=m @@ -653,3 +654,4 @@ CONFIG_CRYPTO_USER_API_AEAD=m # CONFIG_CRYPTO_HW is not set CONFIG_CRC32_SELFTEST=m CONFIG_XZ_DEC_TEST=m +CONFIG_STRING_SELFTEST=m diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig index 72a7764b74ed..3281026a3e15 100644 --- a/arch/m68k/configs/apollo_defconfig +++ b/arch/m68k/configs/apollo_defconfig @@ -422,7 +422,6 @@ CONFIG_NTP_PPS=y CONFIG_PPS_CLIENT_LDISC=m CONFIG_PTP_1588_CLOCK=m # CONFIG_HWMON is not set -# CONFIG_RC_CORE is not set CONFIG_FB=y CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_LOGO=y @@ -554,6 +553,7 @@ CONFIG_TEST_RHASHTABLE=m CONFIG_TEST_HASH=m CONFIG_TEST_USER_COPY=m CONFIG_TEST_BPF=m +CONFIG_TEST_FIND_BIT=m CONFIG_TEST_FIRMWARE=m CONFIG_TEST_SYSCTL=m CONFIG_TEST_UDELAY=m @@ -583,6 +583,7 @@ CONFIG_CRYPTO_RMD256=m CONFIG_CRYPTO_RMD320=m CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_SHA3=m +CONFIG_CRYPTO_SM3=m CONFIG_CRYPTO_TGR192=m CONFIG_CRYPTO_WP512=m CONFIG_CRYPTO_AES_TI=m @@ -612,3 +613,4 @@ CONFIG_CRYPTO_USER_API_AEAD=m # CONFIG_CRYPTO_HW is not set CONFIG_CRC32_SELFTEST=m CONFIG_XZ_DEC_TEST=m +CONFIG_STRING_SELFTEST=m diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig index 884b43a2f0d9..e943fad480cf 100644 --- a/arch/m68k/configs/atari_defconfig +++ b/arch/m68k/configs/atari_defconfig @@ -437,7 +437,6 @@ CONFIG_PPS_CLIENT_LDISC=m CONFIG_PPS_CLIENT_PARPORT=m CONFIG_PTP_1588_CLOCK=m # CONFIG_HWMON is not set -# CONFIG_RC_CORE is not set CONFIG_FB=y CONFIG_FB_ATARI=y CONFIG_FRAMEBUFFER_CONSOLE=y @@ -576,6 +575,7 @@ CONFIG_TEST_RHASHTABLE=m CONFIG_TEST_HASH=m CONFIG_TEST_USER_COPY=m CONFIG_TEST_BPF=m +CONFIG_TEST_FIND_BIT=m CONFIG_TEST_FIRMWARE=m CONFIG_TEST_SYSCTL=m CONFIG_TEST_UDELAY=m @@ -605,6 +605,7 @@ CONFIG_CRYPTO_RMD256=m CONFIG_CRYPTO_RMD320=m CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_SHA3=m +CONFIG_CRYPTO_SM3=m CONFIG_CRYPTO_TGR192=m CONFIG_CRYPTO_WP512=m CONFIG_CRYPTO_AES_TI=m @@ -634,3 +635,4 @@ CONFIG_CRYPTO_USER_API_AEAD=m # CONFIG_CRYPTO_HW is not set CONFIG_CRC32_SELFTEST=m CONFIG_XZ_DEC_TEST=m +CONFIG_STRING_SELFTEST=m diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig index fcfa60d31499..700c2310c336 100644 --- a/arch/m68k/configs/bvme6000_defconfig +++ b/arch/m68k/configs/bvme6000_defconfig @@ -420,7 +420,6 @@ CONFIG_NTP_PPS=y CONFIG_PPS_CLIENT_LDISC=m CONFIG_PTP_1588_CLOCK=m # CONFIG_HWMON is not set -# CONFIG_RC_CORE is not set CONFIG_HID=m CONFIG_HIDRAW=y CONFIG_UHID=m @@ -546,6 +545,7 @@ CONFIG_TEST_RHASHTABLE=m CONFIG_TEST_HASH=m CONFIG_TEST_USER_COPY=m CONFIG_TEST_BPF=m +CONFIG_TEST_FIND_BIT=m CONFIG_TEST_FIRMWARE=m CONFIG_TEST_SYSCTL=m CONFIG_TEST_UDELAY=m @@ -575,6 +575,7 @@ CONFIG_CRYPTO_RMD256=m CONFIG_CRYPTO_RMD320=m CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_SHA3=m +CONFIG_CRYPTO_SM3=m CONFIG_CRYPTO_TGR192=m CONFIG_CRYPTO_WP512=m CONFIG_CRYPTO_AES_TI=m @@ -604,3 +605,4 @@ CONFIG_CRYPTO_USER_API_AEAD=m # CONFIG_CRYPTO_HW is not set CONFIG_CRC32_SELFTEST=m CONFIG_XZ_DEC_TEST=m +CONFIG_STRING_SELFTEST=m diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig index 9d597bbbbbfe..271d57fa4301 100644 --- a/arch/m68k/configs/hp300_defconfig +++ b/arch/m68k/configs/hp300_defconfig @@ -425,7 +425,6 @@ CONFIG_NTP_PPS=y CONFIG_PPS_CLIENT_LDISC=m CONFIG_PTP_1588_CLOCK=m # CONFIG_HWMON is not set -# CONFIG_RC_CORE is not set CONFIG_FB=y CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_LOGO=y @@ -556,6 +555,7 @@ CONFIG_TEST_RHASHTABLE=m CONFIG_TEST_HASH=m CONFIG_TEST_USER_COPY=m CONFIG_TEST_BPF=m +CONFIG_TEST_FIND_BIT=m CONFIG_TEST_FIRMWARE=m CONFIG_TEST_SYSCTL=m CONFIG_TEST_UDELAY=m @@ -585,6 +585,7 @@ CONFIG_CRYPTO_RMD256=m CONFIG_CRYPTO_RMD320=m CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_SHA3=m +CONFIG_CRYPTO_SM3=m CONFIG_CRYPTO_TGR192=m CONFIG_CRYPTO_WP512=m CONFIG_CRYPTO_AES_TI=m @@ -614,3 +615,4 @@ CONFIG_CRYPTO_USER_API_AEAD=m # CONFIG_CRYPTO_HW is not set CONFIG_CRC32_SELFTEST=m CONFIG_XZ_DEC_TEST=m +CONFIG_STRING_SELFTEST=m diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig index 45da20d1286c..88761b867975 100644 --- a/arch/m68k/configs/mac_defconfig +++ b/arch/m68k/configs/mac_defconfig @@ -447,7 +447,6 @@ CONFIG_NTP_PPS=y CONFIG_PPS_CLIENT_LDISC=m CONFIG_PTP_1588_CLOCK=m # CONFIG_HWMON is not set -# CONFIG_RC_CORE is not set CONFIG_FB=y CONFIG_FB_VALKYRIE=y CONFIG_FB_MAC=y @@ -578,6 +577,7 @@ CONFIG_TEST_RHASHTABLE=m CONFIG_TEST_HASH=m CONFIG_TEST_USER_COPY=m CONFIG_TEST_BPF=m +CONFIG_TEST_FIND_BIT=m CONFIG_TEST_FIRMWARE=m CONFIG_TEST_SYSCTL=m CONFIG_TEST_UDELAY=m @@ -607,6 +607,7 @@ CONFIG_CRYPTO_RMD256=m CONFIG_CRYPTO_RMD320=m CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_SHA3=m +CONFIG_CRYPTO_SM3=m CONFIG_CRYPTO_TGR192=m CONFIG_CRYPTO_WP512=m CONFIG_CRYPTO_AES_TI=m @@ -636,3 +637,4 @@ CONFIG_CRYPTO_USER_API_AEAD=m # CONFIG_CRYPTO_HW is not set CONFIG_CRC32_SELFTEST=m CONFIG_XZ_DEC_TEST=m +CONFIG_STRING_SELFTEST=m diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig index fda880c10861..7cb35dadf03b 100644 --- a/arch/m68k/configs/multi_defconfig +++ b/arch/m68k/configs/multi_defconfig @@ -504,7 +504,6 @@ CONFIG_PPS_CLIENT_LDISC=m CONFIG_PPS_CLIENT_PARPORT=m CONFIG_PTP_1588_CLOCK=m # CONFIG_HWMON is not set -# CONFIG_RC_CORE is not set CONFIG_FB=y CONFIG_FB_CIRRUS=y CONFIG_FB_AMIGA=y @@ -658,6 +657,7 @@ CONFIG_TEST_RHASHTABLE=m CONFIG_TEST_HASH=m CONFIG_TEST_USER_COPY=m CONFIG_TEST_BPF=m +CONFIG_TEST_FIND_BIT=m CONFIG_TEST_FIRMWARE=m CONFIG_TEST_SYSCTL=m CONFIG_TEST_UDELAY=m @@ -687,6 +687,7 @@ CONFIG_CRYPTO_RMD256=m CONFIG_CRYPTO_RMD320=m CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_SHA3=m +CONFIG_CRYPTO_SM3=m CONFIG_CRYPTO_TGR192=m CONFIG_CRYPTO_WP512=m CONFIG_CRYPTO_AES_TI=m @@ -716,3 +717,4 @@ CONFIG_CRYPTO_USER_API_AEAD=m # CONFIG_CRYPTO_HW is not set CONFIG_CRC32_SELFTEST=m CONFIG_XZ_DEC_TEST=m +CONFIG_STRING_SELFTEST=m diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig index 7d5e4863efec..b139d7b68393 100644 --- a/arch/m68k/configs/mvme147_defconfig +++ b/arch/m68k/configs/mvme147_defconfig @@ -420,7 +420,6 @@ CONFIG_NTP_PPS=y CONFIG_PPS_CLIENT_LDISC=m CONFIG_PTP_1588_CLOCK=m # CONFIG_HWMON is not set -# CONFIG_RC_CORE is not set CONFIG_HID=m CONFIG_HIDRAW=y CONFIG_UHID=m @@ -546,6 +545,7 @@ CONFIG_TEST_RHASHTABLE=m CONFIG_TEST_HASH=m CONFIG_TEST_USER_COPY=m CONFIG_TEST_BPF=m +CONFIG_TEST_FIND_BIT=m CONFIG_TEST_FIRMWARE=m CONFIG_TEST_SYSCTL=m CONFIG_TEST_UDELAY=m @@ -575,6 +575,7 @@ CONFIG_CRYPTO_RMD256=m CONFIG_CRYPTO_RMD320=m CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_SHA3=m +CONFIG_CRYPTO_SM3=m CONFIG_CRYPTO_TGR192=m CONFIG_CRYPTO_WP512=m CONFIG_CRYPTO_AES_TI=m @@ -604,3 +605,4 @@ CONFIG_CRYPTO_USER_API_AEAD=m # CONFIG_CRYPTO_HW is not set CONFIG_CRC32_SELFTEST=m CONFIG_XZ_DEC_TEST=m +CONFIG_STRING_SELFTEST=m diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig index 7763b71a9c49..398346138769 100644 --- a/arch/m68k/configs/mvme16x_defconfig +++ b/arch/m68k/configs/mvme16x_defconfig @@ -420,7 +420,6 @@ CONFIG_NTP_PPS=y CONFIG_PPS_CLIENT_LDISC=m CONFIG_PTP_1588_CLOCK=m # CONFIG_HWMON is not set -# CONFIG_RC_CORE is not set CONFIG_HID=m CONFIG_HIDRAW=y CONFIG_UHID=m @@ -546,6 +545,7 @@ CONFIG_TEST_RHASHTABLE=m CONFIG_TEST_HASH=m CONFIG_TEST_USER_COPY=m CONFIG_TEST_BPF=m +CONFIG_TEST_FIND_BIT=m CONFIG_TEST_FIRMWARE=m CONFIG_TEST_SYSCTL=m CONFIG_TEST_UDELAY=m @@ -575,6 +575,7 @@ CONFIG_CRYPTO_RMD256=m CONFIG_CRYPTO_RMD320=m CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_SHA3=m +CONFIG_CRYPTO_SM3=m CONFIG_CRYPTO_TGR192=m CONFIG_CRYPTO_WP512=m CONFIG_CRYPTO_AES_TI=m @@ -604,3 +605,4 @@ CONFIG_CRYPTO_USER_API_AEAD=m # CONFIG_CRYPTO_HW is not set CONFIG_CRC32_SELFTEST=m CONFIG_XZ_DEC_TEST=m +CONFIG_STRING_SELFTEST=m diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig index 17eaebfa3e19..14c608326f6d 100644 --- a/arch/m68k/configs/q40_defconfig +++ b/arch/m68k/configs/q40_defconfig @@ -437,7 +437,6 @@ CONFIG_PPS_CLIENT_LDISC=m CONFIG_PPS_CLIENT_PARPORT=m CONFIG_PTP_1588_CLOCK=m # CONFIG_HWMON is not set -# CONFIG_RC_CORE is not set CONFIG_FB=y CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_LOGO=y @@ -569,6 +568,7 @@ CONFIG_TEST_RHASHTABLE=m CONFIG_TEST_HASH=m CONFIG_TEST_USER_COPY=m CONFIG_TEST_BPF=m +CONFIG_TEST_FIND_BIT=m CONFIG_TEST_FIRMWARE=m CONFIG_TEST_SYSCTL=m CONFIG_TEST_UDELAY=m @@ -598,6 +598,7 @@ CONFIG_CRYPTO_RMD256=m CONFIG_CRYPTO_RMD320=m CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_SHA3=m +CONFIG_CRYPTO_SM3=m CONFIG_CRYPTO_TGR192=m CONFIG_CRYPTO_WP512=m CONFIG_CRYPTO_AES_TI=m @@ -627,3 +628,4 @@ CONFIG_CRYPTO_USER_API_AEAD=m # CONFIG_CRYPTO_HW is not set CONFIG_CRC32_SELFTEST=m CONFIG_XZ_DEC_TEST=m +CONFIG_STRING_SELFTEST=m diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig index d1cb7a04ae1d..97dec0bf52f1 100644 --- a/arch/m68k/configs/sun3_defconfig +++ b/arch/m68k/configs/sun3_defconfig @@ -419,7 +419,6 @@ CONFIG_NTP_PPS=y CONFIG_PPS_CLIENT_LDISC=m CONFIG_PTP_1588_CLOCK=m # CONFIG_HWMON is not set -# CONFIG_RC_CORE is not set CONFIG_FB=y CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_LOGO=y @@ -548,6 +547,7 @@ CONFIG_TEST_RHASHTABLE=m CONFIG_TEST_HASH=m CONFIG_TEST_USER_COPY=m CONFIG_TEST_BPF=m +CONFIG_TEST_FIND_BIT=m CONFIG_TEST_FIRMWARE=m CONFIG_TEST_SYSCTL=m CONFIG_TEST_UDELAY=m @@ -576,6 +576,7 @@ CONFIG_CRYPTO_RMD256=m CONFIG_CRYPTO_RMD320=m CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_SHA3=m +CONFIG_CRYPTO_SM3=m CONFIG_CRYPTO_TGR192=m CONFIG_CRYPTO_WP512=m CONFIG_CRYPTO_AES_TI=m @@ -605,3 +606,4 @@ CONFIG_CRYPTO_USER_API_AEAD=m # CONFIG_CRYPTO_HW is not set CONFIG_CRC32_SELFTEST=m CONFIG_XZ_DEC_TEST=m +CONFIG_STRING_SELFTEST=m diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig index ea3a331c62d5..56df28d6d91d 100644 --- a/arch/m68k/configs/sun3x_defconfig +++ b/arch/m68k/configs/sun3x_defconfig @@ -419,7 +419,6 @@ CONFIG_NTP_PPS=y CONFIG_PPS_CLIENT_LDISC=m CONFIG_PTP_1588_CLOCK=m # CONFIG_HWMON is not set -# CONFIG_RC_CORE is not set CONFIG_FB=y CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_LOGO=y @@ -548,6 +547,7 @@ CONFIG_TEST_RHASHTABLE=m CONFIG_TEST_HASH=m CONFIG_TEST_USER_COPY=m CONFIG_TEST_BPF=m +CONFIG_TEST_FIND_BIT=m CONFIG_TEST_FIRMWARE=m CONFIG_TEST_SYSCTL=m CONFIG_TEST_UDELAY=m @@ -577,6 +577,7 @@ CONFIG_CRYPTO_RMD256=m CONFIG_CRYPTO_RMD320=m CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_SHA3=m +CONFIG_CRYPTO_SM3=m CONFIG_CRYPTO_TGR192=m CONFIG_CRYPTO_WP512=m CONFIG_CRYPTO_AES_TI=m @@ -606,3 +607,4 @@ CONFIG_CRYPTO_USER_API_AEAD=m # CONFIG_CRYPTO_HW is not set CONFIG_CRC32_SELFTEST=m CONFIG_XZ_DEC_TEST=m +CONFIG_STRING_SELFTEST=m From 2f828fb21df42058084b16d5e07cecdc30dbc3a5 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sat, 13 Jan 2018 17:37:13 -0500 Subject: [PATCH 02/17] nubus: Avoid array underflow and overflow Check array indices. Avoid sprintf. Use buffers of sufficient size. Use appropriate types for array length parameters. Tested-by: Stan Johnson Signed-off-by: Finn Thain Signed-off-by: Geert Uytterhoeven --- drivers/nubus/nubus.c | 29 +++++++++++++++++------------ drivers/nubus/proc.c | 12 ++++++------ include/linux/nubus.h | 10 ++++------ 3 files changed, 27 insertions(+), 24 deletions(-) diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c index b793727cd4f7..b6c97e07f15e 100644 --- a/drivers/nubus/nubus.c +++ b/drivers/nubus/nubus.c @@ -161,7 +161,7 @@ static unsigned char *nubus_dirptr(const struct nubus_dirent *nd) pointed to with offsets) out of the card ROM. */ void nubus_get_rsrc_mem(void *dest, const struct nubus_dirent *dirent, - int len) + unsigned int len) { unsigned char *t = (unsigned char *)dest; unsigned char *p = nubus_dirptr(dirent); @@ -173,18 +173,22 @@ void nubus_get_rsrc_mem(void *dest, const struct nubus_dirent *dirent, } EXPORT_SYMBOL(nubus_get_rsrc_mem); -void nubus_get_rsrc_str(void *dest, const struct nubus_dirent *dirent, - int len) +void nubus_get_rsrc_str(char *dest, const struct nubus_dirent *dirent, + unsigned int len) { - unsigned char *t = (unsigned char *)dest; + char *t = dest; unsigned char *p = nubus_dirptr(dirent); - while (len) { - *t = nubus_get_rom(&p, 1, dirent->mask); - if (!*t++) + while (len > 1) { + unsigned char c = nubus_get_rom(&p, 1, dirent->mask); + + if (!c) break; + *t++ = c; len--; } + if (len > 0) + *t = '\0'; } EXPORT_SYMBOL(nubus_get_rsrc_str); @@ -468,7 +472,7 @@ nubus_get_functional_resource(struct nubus_board *board, int slot, } case NUBUS_RESID_NAME: { - nubus_get_rsrc_str(dev->name, &ent, 64); + nubus_get_rsrc_str(dev->name, &ent, sizeof(dev->name)); pr_info(" name: %s\n", dev->name); break; } @@ -528,7 +532,7 @@ static int __init nubus_get_vidnames(struct nubus_board *board, /* Don't know what this is yet */ u16 id; /* Longest one I've seen so far is 26 characters */ - char name[32]; + char name[36]; }; pr_info(" video modes supported:\n"); @@ -598,8 +602,8 @@ static int __init nubus_get_vendorinfo(struct nubus_board *board, char name[64]; /* These are all strings, we think */ - nubus_get_rsrc_str(name, &ent, 64); - if (ent.type > 5) + nubus_get_rsrc_str(name, &ent, sizeof(name)); + if (ent.type < 1 || ent.type > 5) ent.type = 5; pr_info(" %s: %s\n", vendor_fields[ent.type - 1], name); } @@ -633,7 +637,8 @@ static int __init nubus_get_board_resource(struct nubus_board *board, int slot, break; } case NUBUS_RESID_NAME: - nubus_get_rsrc_str(board->name, &ent, 64); + nubus_get_rsrc_str(board->name, &ent, + sizeof(board->name)); pr_info(" name: %s\n", board->name); break; case NUBUS_RESID_ICON: diff --git a/drivers/nubus/proc.c b/drivers/nubus/proc.c index 004a122ac0ff..fc20dbcd3b9a 100644 --- a/drivers/nubus/proc.c +++ b/drivers/nubus/proc.c @@ -73,10 +73,10 @@ static void nubus_proc_subdir(struct nubus_dev* dev, /* Some of these are directories, others aren't */ while (nubus_readdir(dir, &ent) != -1) { - char name[8]; + char name[9]; struct proc_dir_entry* e; - sprintf(name, "%x", ent.type); + snprintf(name, sizeof(name), "%x", ent.type); e = proc_create(name, S_IFREG | S_IRUGO | S_IWUSR, parent, &nubus_proc_subdir_fops); if (!e) @@ -95,11 +95,11 @@ static void nubus_proc_populate(struct nubus_dev* dev, /* We know these are all directories (board resource + one or more functional resources) */ while (nubus_readdir(root, &ent) != -1) { - char name[8]; + char name[9]; struct proc_dir_entry* e; struct nubus_dir dir; - sprintf(name, "%x", ent.type); + snprintf(name, sizeof(name), "%x", ent.type); e = proc_mkdir(name, parent); if (!e) return; @@ -119,7 +119,7 @@ int nubus_proc_attach_device(struct nubus_dev *dev) { struct proc_dir_entry *e; struct nubus_dir root; - char name[8]; + char name[9]; if (dev == NULL) { printk(KERN_ERR @@ -135,7 +135,7 @@ int nubus_proc_attach_device(struct nubus_dev *dev) } /* Create a directory */ - sprintf(name, "%x", dev->board->slot); + snprintf(name, sizeof(name), "%x", dev->board->slot); e = dev->procdir = proc_mkdir(name, proc_bus_nubus_dir); if (!e) return -ENOMEM; diff --git a/include/linux/nubus.h b/include/linux/nubus.h index 11ce6b1117a8..d8d63370a28c 100644 --- a/include/linux/nubus.h +++ b/include/linux/nubus.h @@ -126,10 +126,8 @@ int nubus_rewinddir(struct nubus_dir* dir); /* Things to do with directory entries */ int nubus_get_subdir(const struct nubus_dirent* ent, struct nubus_dir* dir); -void nubus_get_rsrc_mem(void* dest, - const struct nubus_dirent *dirent, - int len); -void nubus_get_rsrc_str(void* dest, - const struct nubus_dirent *dirent, - int maxlen); +void nubus_get_rsrc_mem(void *dest, const struct nubus_dirent *dirent, + unsigned int len); +void nubus_get_rsrc_str(char *dest, const struct nubus_dirent *dirent, + unsigned int maxlen); #endif /* LINUX_NUBUS_H */ From 1ff2775a32ef105d9bdbb5f00f20293244a2accc Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sat, 13 Jan 2018 17:37:13 -0500 Subject: [PATCH 03/17] nubus: Fix up header split Due to the '#ifdef __KERNEL__' being located in the wrong place, some definitions from the kernel API were placed in the UAPI header during the scripted header split. Fix this. Also, remove the duplicate comment which is only relevant to the UAPI header. Fixes: 607ca46e97a1 ("UAPI: (Scripted) Disintegrate include/linux") Tested-by: Stan Johnson Signed-off-by: Finn Thain Signed-off-by: Geert Uytterhoeven --- include/linux/nubus.h | 27 +++++++++++++++++++++++---- include/uapi/linux/nubus.h | 23 ----------------------- 2 files changed, 23 insertions(+), 27 deletions(-) diff --git a/include/linux/nubus.h b/include/linux/nubus.h index d8d63370a28c..55b9a4569a69 100644 --- a/include/linux/nubus.h +++ b/include/linux/nubus.h @@ -5,16 +5,28 @@ Originally written by Alan Cox. Hacked to death by C. Scott Ananian and David Huggins-Daines. - - Some of the constants in here are from the corresponding - NetBSD/OpenBSD header file, by Allen Briggs. We figured out the - rest of them on our own. */ +*/ + #ifndef LINUX_NUBUS_H #define LINUX_NUBUS_H #include #include +struct nubus_dir { + unsigned char *base; + unsigned char *ptr; + int done; + int mask; +}; + +struct nubus_dirent { + unsigned char *base; + unsigned char type; + __u32 data; /* Actually 24 bits used */ + int mask; +}; + struct nubus_board { struct nubus_board* next; struct nubus_dev* first_dev; @@ -130,4 +142,11 @@ void nubus_get_rsrc_mem(void *dest, const struct nubus_dirent *dirent, unsigned int len); void nubus_get_rsrc_str(char *dest, const struct nubus_dirent *dirent, unsigned int maxlen); + +/* Returns a pointer to the "standard" slot space. */ +static inline void *nubus_slot_addr(int slot) +{ + return (void *)(0xF0000000 | (slot << 24)); +} + #endif /* LINUX_NUBUS_H */ diff --git a/include/uapi/linux/nubus.h b/include/uapi/linux/nubus.h index f3776cc80f4d..48031e7858f1 100644 --- a/include/uapi/linux/nubus.h +++ b/include/uapi/linux/nubus.h @@ -221,27 +221,4 @@ enum nubus_display_res_id { NUBUS_RESID_SIXTHMODE = 0x0085 }; -struct nubus_dir -{ - unsigned char *base; - unsigned char *ptr; - int done; - int mask; -}; - -struct nubus_dirent -{ - unsigned char *base; - unsigned char type; - __u32 data; /* Actually 24bits used */ - int mask; -}; - - -/* We'd like to get rid of this eventually. Only daynaport.c uses it now. */ -static inline void *nubus_slot_addr(int slot) -{ - return (void *)(0xF0000000|(slot<<24)); -} - #endif /* _UAPILINUX_NUBUS_H */ From 460cf95e8b6cda2823a6432253ae91d3e1e7a021 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sat, 13 Jan 2018 17:37:13 -0500 Subject: [PATCH 04/17] nubus: Use static functions where possible This fixes a couple of warnings from 'make W=1': drivers/nubus/nubus.c:790: warning: no previous prototype for 'nubus_probe_slot' drivers/nubus/nubus.c:824: warning: no previous prototype for 'nubus_scan_bus' Tested-by: Stan Johnson Signed-off-by: Finn Thain Signed-off-by: Geert Uytterhoeven --- drivers/nubus/nubus.c | 4 ++-- include/linux/nubus.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c index b6c97e07f15e..35056cee94b1 100644 --- a/drivers/nubus/nubus.c +++ b/drivers/nubus/nubus.c @@ -793,7 +793,7 @@ static struct nubus_board * __init nubus_add_board(int slot, int bytelanes) return board; } -void __init nubus_probe_slot(int slot) +static void __init nubus_probe_slot(int slot) { unsigned char dp; unsigned char *rp; @@ -827,7 +827,7 @@ void __init nubus_probe_slot(int slot) } } -void __init nubus_scan_bus(void) +static void __init nubus_scan_bus(void) { int slot; diff --git a/include/linux/nubus.h b/include/linux/nubus.h index 55b9a4569a69..e525669f1991 100644 --- a/include/linux/nubus.h +++ b/include/linux/nubus.h @@ -92,7 +92,6 @@ extern struct nubus_dev* nubus_devices; extern struct nubus_board* nubus_boards; /* Generic NuBus interface functions, modelled after the PCI interface */ -void nubus_scan_bus(void); #ifdef CONFIG_PROC_FS extern void nubus_proc_init(void); #else From f53bad0881a35c45d89bd8c552dc0498b96403c5 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sat, 13 Jan 2018 17:37:13 -0500 Subject: [PATCH 05/17] nubus: Fix log spam Testing shows that a single Radius PrecisionColor 24X display board, which has 95 functional resources, produces over a thousand lines of log messages. Suppress these messages with pr_debug(). Remove some redundant messages relating to nubus_get_subdir() calls. Fix the format block debug messages as the sequence of entries is backwards (my bad). Move the "scanning slots" message to its proper location. Fixes: 71ae40e4cf33 ("nubus: Clean up printk calls") Tested-by: Stan Johnson Signed-off-by: Finn Thain Signed-off-by: Geert Uytterhoeven --- drivers/nubus/nubus.c | 127 ++++++++++++++++++------------------------ 1 file changed, 55 insertions(+), 72 deletions(-) diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c index 35056cee94b1..ef3a115920ca 100644 --- a/drivers/nubus/nubus.c +++ b/drivers/nubus/nubus.c @@ -353,15 +353,15 @@ static int __init nubus_show_display_resource(struct nubus_dev *dev, { switch (ent->type) { case NUBUS_RESID_GAMMADIR: - pr_info(" gamma directory offset: 0x%06x\n", ent->data); + pr_debug(" gamma directory offset: 0x%06x\n", ent->data); break; case 0x0080 ... 0x0085: - pr_info(" mode %02X info offset: 0x%06x\n", - ent->type, ent->data); + pr_debug(" mode 0x%02x info offset: 0x%06x\n", + ent->type, ent->data); break; default: - pr_info(" unknown resource %02X, data 0x%06x\n", - ent->type, ent->data); + pr_debug(" unknown resource 0x%02x, data 0x%06x\n", + ent->type, ent->data); } return 0; } @@ -375,12 +375,12 @@ static int __init nubus_show_network_resource(struct nubus_dev *dev, char addr[6]; nubus_get_rsrc_mem(addr, ent, 6); - pr_info(" MAC address: %pM\n", addr); + pr_debug(" MAC address: %pM\n", addr); break; } default: - pr_info(" unknown resource %02X, data 0x%06x\n", - ent->type, ent->data); + pr_debug(" unknown resource 0x%02x, data 0x%06x\n", + ent->type, ent->data); } return 0; } @@ -394,8 +394,8 @@ static int __init nubus_show_cpu_resource(struct nubus_dev *dev, unsigned long meminfo[2]; nubus_get_rsrc_mem(&meminfo, ent, 8); - pr_info(" memory: [ 0x%08lx 0x%08lx ]\n", - meminfo[0], meminfo[1]); + pr_debug(" memory: [ 0x%08lx 0x%08lx ]\n", + meminfo[0], meminfo[1]); break; } case NUBUS_RESID_ROMINFO: @@ -403,13 +403,13 @@ static int __init nubus_show_cpu_resource(struct nubus_dev *dev, unsigned long rominfo[2]; nubus_get_rsrc_mem(&rominfo, ent, 8); - pr_info(" ROM: [ 0x%08lx 0x%08lx ]\n", - rominfo[0], rominfo[1]); + pr_debug(" ROM: [ 0x%08lx 0x%08lx ]\n", + rominfo[0], rominfo[1]); break; } default: - pr_info(" unknown resource %02X, data 0x%06x\n", - ent->type, ent->data); + pr_debug(" unknown resource 0x%02x, data 0x%06x\n", + ent->type, ent->data); } return 0; } @@ -428,8 +428,8 @@ static int __init nubus_show_private_resource(struct nubus_dev *dev, nubus_show_cpu_resource(dev, ent); break; default: - pr_info(" unknown resource %02X, data 0x%06x\n", - ent->type, ent->data); + pr_debug(" unknown resource 0x%02x, data 0x%06x\n", + ent->type, ent->data); } return 0; } @@ -442,12 +442,9 @@ nubus_get_functional_resource(struct nubus_board *board, int slot, struct nubus_dirent ent; struct nubus_dev *dev; - pr_info(" Function 0x%02x:\n", parent->type); + pr_debug(" Functional resource 0x%02x:\n", parent->type); nubus_get_subdir(parent, &dir); - pr_debug("%s: parent is 0x%p, dir is 0x%p\n", - __func__, parent->base, dir.base); - /* Actually we should probably panic if this fails */ if ((dev = kzalloc(sizeof(*dev), GFP_ATOMIC)) == NULL) return NULL; @@ -466,14 +463,14 @@ nubus_get_functional_resource(struct nubus_board *board, int slot, dev->type = nbtdata[1]; dev->dr_sw = nbtdata[2]; dev->dr_hw = nbtdata[3]; - pr_info(" type: [cat 0x%x type 0x%x sw 0x%x hw 0x%x]\n", - nbtdata[0], nbtdata[1], nbtdata[2], nbtdata[3]); + pr_debug(" type: [cat 0x%x type 0x%x sw 0x%x hw 0x%x]\n", + nbtdata[0], nbtdata[1], nbtdata[2], nbtdata[3]); break; } case NUBUS_RESID_NAME: { nubus_get_rsrc_str(dev->name, &ent, sizeof(dev->name)); - pr_info(" name: %s\n", dev->name); + pr_debug(" name: %s\n", dev->name); break; } case NUBUS_RESID_DRVRDIR: @@ -486,7 +483,7 @@ nubus_get_functional_resource(struct nubus_board *board, int slot, nubus_get_subdir(&ent, &drvr_dir); nubus_readdir(&drvr_dir, &drvr_ent); dev->driver = nubus_dirptr(&drvr_ent); - pr_info(" driver at: 0x%p\n", dev->driver); + pr_debug(" driver at: 0x%p\n", dev->driver); break; } case NUBUS_RESID_MINOR_BASEOS: @@ -494,20 +491,20 @@ nubus_get_functional_resource(struct nubus_board *board, int slot, multiple framebuffers. It might be handy for Ethernet as well */ nubus_get_rsrc_mem(&dev->iobase, &ent, 4); - pr_info(" memory offset: 0x%08lx\n", dev->iobase); + pr_debug(" memory offset: 0x%08lx\n", dev->iobase); break; case NUBUS_RESID_MINOR_LENGTH: /* Ditto */ nubus_get_rsrc_mem(&dev->iosize, &ent, 4); - pr_info(" memory length: 0x%08lx\n", dev->iosize); + pr_debug(" memory length: 0x%08lx\n", dev->iosize); break; case NUBUS_RESID_FLAGS: dev->flags = ent.data; - pr_info(" flags: 0x%06x\n", dev->flags); + pr_debug(" flags: 0x%06x\n", dev->flags); break; case NUBUS_RESID_HWDEVID: dev->hwdevid = ent.data; - pr_info(" hwdevid: 0x%06x\n", dev->hwdevid); + pr_debug(" hwdevid: 0x%06x\n", dev->hwdevid); break; default: /* Local/Private resources have their own @@ -535,10 +532,8 @@ static int __init nubus_get_vidnames(struct nubus_board *board, char name[36]; }; - pr_info(" video modes supported:\n"); + pr_debug(" video modes supported:\n"); nubus_get_subdir(parent, &dir); - pr_debug("%s: parent is 0x%p, dir is 0x%p\n", - __func__, parent->base, dir.base); while (nubus_readdir(&dir, &ent) != -1) { struct vidmode mode; @@ -552,7 +547,7 @@ static int __init nubus_get_vidnames(struct nubus_board *board, size = sizeof(mode) - 1; memset(&mode, 0, sizeof(mode)); nubus_get_rsrc_mem(&mode, &ent, size); - pr_info(" %02X: (%02X) %s\n", ent.type, + pr_debug(" 0x%02x: 0x%04x %s\n", ent.type, mode.id, mode.name); } return 0; @@ -563,25 +558,16 @@ static int __init nubus_get_icon(struct nubus_board *board, const struct nubus_dirent *ent) { /* Should be 32x32 if my memory serves me correctly */ - unsigned char icon[128]; - int x, y; + u32 icon[32]; + int i; nubus_get_rsrc_mem(&icon, ent, 128); - pr_info(" icon:\n"); + pr_debug(" icon:\n"); + for (i = 0; i < 8; i++) + pr_debug(" %08x %08x %08x %08x\n", + icon[i * 4 + 0], icon[i * 4 + 1], + icon[i * 4 + 2], icon[i * 4 + 3]); - /* We should actually plot these somewhere in the framebuffer - init. This is just to demonstrate that they do, in fact, - exist */ - for (y = 0; y < 32; y++) { - pr_info(" "); - for (x = 0; x < 32; x++) { - if (icon[y * 4 + x / 8] & (0x80 >> (x % 8))) - pr_cont("*"); - else - pr_cont(" "); - } - pr_cont("\n"); - } return 0; } @@ -593,10 +579,8 @@ static int __init nubus_get_vendorinfo(struct nubus_board *board, static char *vendor_fields[6] = { "ID", "serial", "revision", "part", "date", "unknown field" }; - pr_info(" vendor info:\n"); + pr_debug(" vendor info:\n"); nubus_get_subdir(parent, &dir); - pr_debug("%s: parent is 0x%p, dir is 0x%p\n", - __func__, parent->base, dir.base); while (nubus_readdir(&dir, &ent) != -1) { char name[64]; @@ -605,7 +589,7 @@ static int __init nubus_get_vendorinfo(struct nubus_board *board, nubus_get_rsrc_str(name, &ent, sizeof(name)); if (ent.type < 1 || ent.type > 5) ent.type = 5; - pr_info(" %s: %s\n", vendor_fields[ent.type - 1], name); + pr_debug(" %s: %s\n", vendor_fields[ent.type - 1], name); } return 0; } @@ -616,9 +600,8 @@ static int __init nubus_get_board_resource(struct nubus_board *board, int slot, struct nubus_dir dir; struct nubus_dirent ent; + pr_debug(" Board resource 0x%02x:\n", parent->type); nubus_get_subdir(parent, &dir); - pr_debug("%s: parent is 0x%p, dir is 0x%p\n", - __func__, parent->base, dir.base); while (nubus_readdir(&dir, &ent) != -1) { switch (ent.type) { @@ -629,8 +612,8 @@ static int __init nubus_get_board_resource(struct nubus_board *board, int slot, useful except insofar as it tells us that we really are looking at a board resource. */ nubus_get_rsrc_mem(nbtdata, &ent, 8); - pr_info(" type: [cat 0x%x type 0x%x sw 0x%x hw 0x%x]\n", - nbtdata[0], nbtdata[1], nbtdata[2], nbtdata[3]); + pr_debug(" type: [cat 0x%x type 0x%x sw 0x%x hw 0x%x]\n", + nbtdata[0], nbtdata[1], nbtdata[2], nbtdata[3]); if (nbtdata[0] != 1 || nbtdata[1] != 0 || nbtdata[2] != 0 || nbtdata[3] != 0) pr_err("this sResource is not a board resource!\n"); @@ -639,28 +622,29 @@ static int __init nubus_get_board_resource(struct nubus_board *board, int slot, case NUBUS_RESID_NAME: nubus_get_rsrc_str(board->name, &ent, sizeof(board->name)); - pr_info(" name: %s\n", board->name); + pr_debug(" name: %s\n", board->name); break; case NUBUS_RESID_ICON: nubus_get_icon(board, &ent); break; case NUBUS_RESID_BOARDID: - pr_info(" board id: 0x%x\n", ent.data); + pr_debug(" board id: 0x%x\n", ent.data); break; case NUBUS_RESID_PRIMARYINIT: - pr_info(" primary init offset: 0x%06x\n", ent.data); + pr_debug(" primary init offset: 0x%06x\n", ent.data); break; case NUBUS_RESID_VENDORINFO: nubus_get_vendorinfo(board, &ent); break; case NUBUS_RESID_FLAGS: - pr_info(" flags: 0x%06x\n", ent.data); + pr_debug(" flags: 0x%06x\n", ent.data); break; case NUBUS_RESID_HWDEVID: - pr_info(" hwdevid: 0x%06x\n", ent.data); + pr_debug(" hwdevid: 0x%06x\n", ent.data); break; case NUBUS_RESID_SECONDINIT: - pr_info(" secondary init offset: 0x%06x\n", ent.data); + pr_debug(" secondary init offset: 0x%06x\n", + ent.data); break; /* WTF isn't this in the functional resources? */ case NUBUS_RESID_VIDNAMES: @@ -668,12 +652,12 @@ static int __init nubus_get_board_resource(struct nubus_board *board, int slot, break; /* Same goes for this */ case NUBUS_RESID_VIDMODES: - pr_info(" video mode parameter directory offset: 0x%06x\n", - ent.data); + pr_debug(" video mode parameter directory offset: 0x%06x\n", + ent.data); break; default: - pr_info(" unknown resource %02X, data 0x%06x\n", - ent.type, ent.data); + pr_debug(" unknown resource 0x%02x, data 0x%06x\n", + ent.type, ent.data); } } return 0; @@ -700,14 +684,14 @@ static struct nubus_board * __init nubus_add_board(int slot, int bytelanes) /* Dump the format block for debugging purposes */ pr_debug("Slot %X, format block at 0x%p:\n", slot, rp); + pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes)); + pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes)); + pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes)); pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes)); pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes)); pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes)); pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes)); pr_debug("%02lx\n", nubus_get_rom(&rp, 1, bytelanes)); - pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes)); - pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes)); - pr_debug("%08lx\n", nubus_get_rom(&rp, 4, bytelanes)); rp = board->fblock; board->slot = slot; @@ -747,7 +731,7 @@ static struct nubus_board * __init nubus_add_board(int slot, int bytelanes) nubus_get_root_dir(board, &dir); /* We're ready to rock */ - pr_info("Slot %X:\n", slot); + pr_debug("Slot %X resources:\n", slot); /* Each slot should have one board resource and any number of functional resources. So we'll fill in some fields in the @@ -759,7 +743,6 @@ static struct nubus_board * __init nubus_add_board(int slot, int bytelanes) pr_err("Board resource not found!\n"); return NULL; } else { - pr_info(" Board resource:\n"); nubus_get_board_resource(board, slot, &ent); } @@ -831,6 +814,7 @@ static void __init nubus_scan_bus(void) { int slot; + pr_info("NuBus: Scanning NuBus slots.\n"); for (slot = 9; slot < 15; slot++) { nubus_probe_slot(slot); } @@ -841,7 +825,6 @@ static int __init nubus_init(void) if (!MACH_IS_MAC) return 0; - pr_info("NuBus: Scanning NuBus slots.\n"); nubus_devices = NULL; nubus_boards = NULL; nubus_scan_bus(); From d7811a3678eac540a43d9fd3dda7867280844836 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sat, 13 Jan 2018 17:37:13 -0500 Subject: [PATCH 06/17] nubus: Validate slot resource IDs While we are here, include the slot number in the related error messages. Tested-by: Stan Johnson Signed-off-by: Finn Thain Signed-off-by: Geert Uytterhoeven --- drivers/nubus/nubus.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c index ef3a115920ca..e7c7e49a074a 100644 --- a/drivers/nubus/nubus.c +++ b/drivers/nubus/nubus.c @@ -616,7 +616,8 @@ static int __init nubus_get_board_resource(struct nubus_board *board, int slot, nbtdata[0], nbtdata[1], nbtdata[2], nbtdata[3]); if (nbtdata[0] != 1 || nbtdata[1] != 0 || nbtdata[2] != 0 || nbtdata[3] != 0) - pr_err("this sResource is not a board resource!\n"); + pr_err("Slot %X: sResource is not a board resource!\n", + slot); break; } case NUBUS_RESID_NAME: @@ -672,6 +673,7 @@ static struct nubus_board * __init nubus_add_board(int slot, int bytelanes) unsigned long dpat; struct nubus_dir dir; struct nubus_dirent ent; + int prev_resid = -1; /* Move to the start of the format block */ rp = nubus_rom_addr(slot); @@ -711,10 +713,10 @@ static struct nubus_board * __init nubus_add_board(int slot, int bytelanes) /* Directory offset should be small and negative... */ if (!(board->doffset & 0x00FF0000)) - pr_warn("Dodgy doffset!\n"); + pr_warn("Slot %X: Dodgy doffset!\n", slot); dpat = nubus_get_rom(&rp, 4, bytelanes); if (dpat != NUBUS_TEST_PATTERN) - pr_warn("Wrong test pattern %08lx!\n", dpat); + pr_warn("Slot %X: Wrong test pattern %08lx!\n", slot, dpat); /* * I wonder how the CRC is meant to work - @@ -740,12 +742,15 @@ static struct nubus_board * __init nubus_add_board(int slot, int bytelanes) for each of them. */ if (nubus_readdir(&dir, &ent) == -1) { /* We can't have this! */ - pr_err("Board resource not found!\n"); + pr_err("Slot %X: Board resource not found!\n", slot); return NULL; - } else { - nubus_get_board_resource(board, slot, &ent); } + if (ent.type < 1 || ent.type > 127) + pr_warn("Slot %X: Board resource ID is invalid!\n", slot); + + nubus_get_board_resource(board, slot, &ent); + while (nubus_readdir(&dir, &ent) != -1) { struct nubus_dev *dev; struct nubus_dev **devp; @@ -754,6 +759,15 @@ static struct nubus_board * __init nubus_add_board(int slot, int bytelanes) if (dev == NULL) continue; + /* Resources should appear in ascending ID order. This sanity + * check prevents duplicate resource IDs. + */ + if (dev->resid <= prev_resid) { + kfree(dev); + continue; + } + prev_resid = dev->resid; + /* We zeroed this out above */ if (board->first_dev == NULL) board->first_dev = dev; From 6c8b89ea55c9d53979e2be7977e945edba100359 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sat, 13 Jan 2018 17:37:13 -0500 Subject: [PATCH 07/17] nubus: Call proc_mkdir() not more than once per slot directory This patch fixes the following WARNING. proc_dir_entry 'nubus/a' already registered Modules linked in: CPU: 0 PID: 1 Comm: swapper Tainted: G W 4.13.0-00036-gd57552077387 #1 Stack from 01c1bd9c: 01c1bd9c 003c2c8b 01c1bdc0 0001b0fe 00000000 00322f4a 01c43a20 01c43b0c 01c8c420 01c1bde8 0001b1b8 003a4ac3 00000148 000faa26 00000009 00000000 01c1bde0 003a4b6c 01c1bdfc 01c1be20 000faa26 003a4ac3 00000148 003a4b6c 01c43a71 01c8c471 01c10000 00326430 0043d00c 00000005 01c71a00 0020bce0 00322964 01c1be38 000fac04 01c43a20 01c8c420 01c1bee0 01c8c420 01c1be50 000fac4c 01c1bee0 00000000 01c43a20 00000000 01c1bee8 0020bd26 01c1bee0 Call Trace: [<0001b0fe>] __warn+0xae/0xde [<00322f4a>] memcmp+0x0/0x5c [<0001b1b8>] warn_slowpath_fmt+0x2e/0x36 [<000faa26>] proc_register+0xbe/0xd8 [<000faa26>] proc_register+0xbe/0xd8 [<00326430>] sprintf+0x0/0x20 [<0020bce0>] nubus_proc_attach_device+0x0/0x1b8 [<00322964>] strcpy+0x0/0x22 [<000fac04>] proc_mkdir_data+0x64/0x96 [<000fac4c>] proc_mkdir+0x16/0x1c [<0020bd26>] nubus_proc_attach_device+0x46/0x1b8 [<0020bce0>] nubus_proc_attach_device+0x0/0x1b8 [<00322964>] strcpy+0x0/0x22 [<00001ba6>] kernel_pg_dir+0xba6/0x1000 [<004339a2>] proc_bus_nubus_add_devices+0x1a/0x2e [<000faa40>] proc_create_data+0x0/0xf2 [<0003297c>] parse_args+0x0/0x2d4 [<00433a08>] nubus_proc_init+0x52/0x5a [<00433944>] nubus_init+0x0/0x44 [<00433982>] nubus_init+0x3e/0x44 [<000020dc>] do_one_initcall+0x38/0x196 [<000020a4>] do_one_initcall+0x0/0x196 [<0003297c>] parse_args+0x0/0x2d4 [<00322964>] strcpy+0x0/0x22 [<00040004>] __up_read+0xe/0x40 [<004231d4>] repair_env_string+0x0/0x7a [<0042312e>] kernel_init_freeable+0xee/0x194 [<00423146>] kernel_init_freeable+0x106/0x194 [<00433944>] nubus_init+0x0/0x44 [<000a6000>] kfree+0x0/0x156 [<0032768c>] kernel_init+0x0/0xda [<00327698>] kernel_init+0xc/0xda [<0032768c>] kernel_init+0x0/0xda [<00002a90>] ret_from_kernel_thread+0xc/0x14 ---[ end trace 14a6d619908ea253 ]--- ------------[ cut here ]------------ This gets repeated with each additional functional reasource. The problem here is the call to proc_mkdir() when the directory already exists. Each nubus_board gets a directory, such as /proc/bus/nubus/s/ where s is the hex slot number. Therefore, store the 'procdir' pointer in struct nubus_board instead of struct nubus_dev. Tested-by: Stan Johnson Signed-off-by: Finn Thain Signed-off-by: Geert Uytterhoeven --- drivers/nubus/proc.c | 6 +++++- include/linux/nubus.h | 5 +++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/nubus/proc.c b/drivers/nubus/proc.c index fc20dbcd3b9a..91211192f36f 100644 --- a/drivers/nubus/proc.c +++ b/drivers/nubus/proc.c @@ -134,9 +134,13 @@ int nubus_proc_attach_device(struct nubus_dev *dev) return -1; } + if (dev->board->procdir) + return 0; + /* Create a directory */ snprintf(name, sizeof(name), "%x", dev->board->slot); - e = dev->procdir = proc_mkdir(name, proc_bus_nubus_dir); + e = proc_mkdir(name, proc_bus_nubus_dir); + dev->board->procdir = e; if (!e) return -ENOMEM; diff --git a/include/linux/nubus.h b/include/linux/nubus.h index e525669f1991..2245430e1357 100644 --- a/include/linux/nubus.h +++ b/include/linux/nubus.h @@ -53,13 +53,14 @@ struct nubus_board { unsigned char rev; unsigned char format; unsigned char lanes; + + /* Directory entry in /proc/bus/nubus */ + struct proc_dir_entry *procdir; }; struct nubus_dev { /* Next link in device list */ struct nubus_dev* next; - /* Directory entry in /proc/bus/nubus */ - struct proc_dir_entry* procdir; /* The functional resource ID of this device */ unsigned char resid; From 9f97977deb22e602f91047a105b961ffb36adc2b Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sat, 13 Jan 2018 17:37:13 -0500 Subject: [PATCH 08/17] nubus: Remove redundant code Eliminate unused values from struct nubus_dev to save wasted memory (a Radius PrecisionColor 24X card has about 95 functional resources and up to six such cards may be fitted). Also remove redundant static variable initialization, an unreachable !MACH_IS_MAC conditional, the unused nubus_find_device() function, the bogus get_nubus_list() prototype and the pointless card_present temporary variable. Tested-by: Stan Johnson Signed-off-by: Finn Thain Signed-off-by: Geert Uytterhoeven --- drivers/nubus/nubus.c | 57 +++++++++++++++++-------------------------- drivers/nubus/proc.c | 2 -- include/linux/nubus.h | 17 +------------ 3 files changed, 23 insertions(+), 53 deletions(-) diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c index e7c7e49a074a..4ae5c420f13f 100644 --- a/drivers/nubus/nubus.c +++ b/drivers/nubus/nubus.c @@ -281,23 +281,6 @@ EXPORT_SYMBOL(nubus_rewinddir); /* Driver interface functions, more or less like in pci.c */ -struct nubus_dev* -nubus_find_device(unsigned short category, unsigned short type, - unsigned short dr_hw, unsigned short dr_sw, - const struct nubus_dev *from) -{ - struct nubus_dev *itor = from ? from->next : nubus_devices; - - while (itor) { - if (itor->category == category && itor->type == type && - itor->dr_hw == dr_hw && itor->dr_sw == dr_sw) - return itor; - itor = itor->next; - } - return NULL; -} -EXPORT_SYMBOL(nubus_find_device); - struct nubus_dev* nubus_find_type(unsigned short category, unsigned short type, const struct nubus_dev *from) @@ -469,8 +452,10 @@ nubus_get_functional_resource(struct nubus_board *board, int slot, } case NUBUS_RESID_NAME: { - nubus_get_rsrc_str(dev->name, &ent, sizeof(dev->name)); - pr_debug(" name: %s\n", dev->name); + char name[64]; + + nubus_get_rsrc_str(name, &ent, sizeof(name)); + pr_debug(" name: %s\n", name); break; } case NUBUS_RESID_DRVRDIR: @@ -479,32 +464,39 @@ nubus_get_functional_resource(struct nubus_board *board, int slot, use this :-) */ struct nubus_dir drvr_dir; struct nubus_dirent drvr_ent; + unsigned char *driver; nubus_get_subdir(&ent, &drvr_dir); nubus_readdir(&drvr_dir, &drvr_ent); - dev->driver = nubus_dirptr(&drvr_ent); - pr_debug(" driver at: 0x%p\n", dev->driver); + driver = nubus_dirptr(&drvr_ent); + pr_debug(" driver at: 0x%p\n", driver); break; } case NUBUS_RESID_MINOR_BASEOS: + { /* We will need this in order to support multiple framebuffers. It might be handy for Ethernet as well */ - nubus_get_rsrc_mem(&dev->iobase, &ent, 4); - pr_debug(" memory offset: 0x%08lx\n", dev->iobase); + u32 base_offset; + + nubus_get_rsrc_mem(&base_offset, &ent, 4); + pr_debug(" memory offset: 0x%08x\n", base_offset); break; + } case NUBUS_RESID_MINOR_LENGTH: + { /* Ditto */ - nubus_get_rsrc_mem(&dev->iosize, &ent, 4); - pr_debug(" memory length: 0x%08lx\n", dev->iosize); + u32 length; + + nubus_get_rsrc_mem(&length, &ent, 4); + pr_debug(" memory length: 0x%08x\n", length); break; + } case NUBUS_RESID_FLAGS: - dev->flags = ent.data; - pr_debug(" flags: 0x%06x\n", dev->flags); + pr_debug(" flags: 0x%06x\n", ent.data); break; case NUBUS_RESID_HWDEVID: - dev->hwdevid = ent.data; - pr_debug(" hwdevid: 0x%06x\n", dev->hwdevid); + pr_debug(" hwdevid: 0x%06x\n", ent.data); break; default: /* Local/Private resources have their own @@ -798,11 +790,8 @@ static void __init nubus_probe_slot(int slot) rp = nubus_rom_addr(slot); for (i = 4; i; i--) { - int card_present; - rp--; - card_present = hwreg_present(rp); - if (!card_present) + if (!hwreg_present(rp)) continue; dp = *rp; @@ -839,8 +828,6 @@ static int __init nubus_init(void) if (!MACH_IS_MAC) return 0; - nubus_devices = NULL; - nubus_boards = NULL; nubus_scan_bus(); nubus_proc_init(); return 0; diff --git a/drivers/nubus/proc.c b/drivers/nubus/proc.c index 91211192f36f..41ec859bdd8b 100644 --- a/drivers/nubus/proc.c +++ b/drivers/nubus/proc.c @@ -230,8 +230,6 @@ void __init proc_bus_nubus_add_devices(void) void __init nubus_proc_init(void) { proc_create("nubus", 0, NULL, &nubus_proc_fops); - if (!MACH_IS_MAC) - return; proc_bus_nubus_dir = proc_mkdir("bus/nubus", NULL); proc_create("devices", 0, proc_bus_nubus_dir, &nubus_devices_proc_fops); proc_bus_nubus_add_devices(); diff --git a/include/linux/nubus.h b/include/linux/nubus.h index 2245430e1357..3c7b236074b3 100644 --- a/include/linux/nubus.h +++ b/include/linux/nubus.h @@ -70,16 +70,6 @@ struct nubus_dev { unsigned short type; unsigned short dr_sw; unsigned short dr_hw; - /* This is the device's name rather than the board's. - Sometimes they are different. Usually the board name is - more correct. */ - char name[64]; - /* MacOS driver (I kid you not) */ - unsigned char* driver; - /* Actually this is an offset */ - unsigned long iobase; - unsigned long iosize; - unsigned char flags, hwdevid; /* Functional directory */ unsigned char* directory; @@ -98,14 +88,9 @@ extern void nubus_proc_init(void); #else static inline void nubus_proc_init(void) {} #endif -int get_nubus_list(char *buf); + int nubus_proc_attach_device(struct nubus_dev *dev); /* If we need more precision we can add some more of these */ -struct nubus_dev* nubus_find_device(unsigned short category, - unsigned short type, - unsigned short dr_hw, - unsigned short dr_sw, - const struct nubus_dev* from); struct nubus_dev* nubus_find_type(unsigned short category, unsigned short type, const struct nubus_dev* from); From 4bccc4b629de3af24308a24c41aff6270a6404aa Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sat, 13 Jan 2018 17:37:13 -0500 Subject: [PATCH 09/17] nubus: Clean up whitespace Tested-by: Stan Johnson Signed-off-by: Finn Thain Signed-off-by: Geert Uytterhoeven --- include/linux/nubus.h | 58 +++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/include/linux/nubus.h b/include/linux/nubus.h index 3c7b236074b3..2d6f04055ebe 100644 --- a/include/linux/nubus.h +++ b/include/linux/nubus.h @@ -28,9 +28,9 @@ struct nubus_dirent { }; struct nubus_board { - struct nubus_board* next; - struct nubus_dev* first_dev; - + struct nubus_board *next; + struct nubus_dev *first_dev; + /* Only 9-E actually exist, though 0-8 are also theoretically possible, and 0 is a special case which represents the motherboard and onboard peripherals (Ethernet, video) */ @@ -39,10 +39,10 @@ struct nubus_board { char name[64]; /* Format block */ - unsigned char* fblock; + unsigned char *fblock; /* Root directory (does *not* always equal fblock + doffset!) */ - unsigned char* directory; - + unsigned char *directory; + unsigned long slot_addr; /* Offset to root directory (sometimes) */ unsigned long doffset; @@ -60,7 +60,7 @@ struct nubus_board { struct nubus_dev { /* Next link in device list */ - struct nubus_dev* next; + struct nubus_dev *next; /* The functional resource ID of this device */ unsigned char resid; @@ -70,17 +70,17 @@ struct nubus_dev { unsigned short type; unsigned short dr_sw; unsigned short dr_hw; - + /* Functional directory */ - unsigned char* directory; + unsigned char *directory; /* Much of our info comes from here */ - struct nubus_board* board; + struct nubus_board *board; }; /* This is all NuBus devices (used to find devices later on) */ -extern struct nubus_dev* nubus_devices; +extern struct nubus_dev *nubus_devices; /* This is all NuBus cards */ -extern struct nubus_board* nubus_boards; +extern struct nubus_board *nubus_boards; /* Generic NuBus interface functions, modelled after the PCI interface */ #ifdef CONFIG_PROC_FS @@ -91,38 +91,38 @@ static inline void nubus_proc_init(void) {} int nubus_proc_attach_device(struct nubus_dev *dev); /* If we need more precision we can add some more of these */ -struct nubus_dev* nubus_find_type(unsigned short category, +struct nubus_dev *nubus_find_type(unsigned short category, unsigned short type, - const struct nubus_dev* from); + const struct nubus_dev *from); /* Might have more than one device in a slot, you know... */ -struct nubus_dev* nubus_find_slot(unsigned int slot, - const struct nubus_dev* from); +struct nubus_dev *nubus_find_slot(unsigned int slot, + const struct nubus_dev *from); /* These are somewhat more NuBus-specific. They all return 0 for success and -1 for failure, as you'd expect. */ /* The root directory which contains the board and functional directories */ -int nubus_get_root_dir(const struct nubus_board* board, - struct nubus_dir* dir); +int nubus_get_root_dir(const struct nubus_board *board, + struct nubus_dir *dir); /* The board directory */ -int nubus_get_board_dir(const struct nubus_board* board, - struct nubus_dir* dir); +int nubus_get_board_dir(const struct nubus_board *board, + struct nubus_dir *dir); /* The functional directory */ -int nubus_get_func_dir(const struct nubus_dev* dev, - struct nubus_dir* dir); +int nubus_get_func_dir(const struct nubus_dev *dev, + struct nubus_dir *dir); /* These work on any directory gotten via the above */ -int nubus_readdir(struct nubus_dir* dir, - struct nubus_dirent* ent); -int nubus_find_rsrc(struct nubus_dir* dir, +int nubus_readdir(struct nubus_dir *dir, + struct nubus_dirent *ent); +int nubus_find_rsrc(struct nubus_dir *dir, unsigned char rsrc_type, - struct nubus_dirent* ent); -int nubus_rewinddir(struct nubus_dir* dir); + struct nubus_dirent *ent); +int nubus_rewinddir(struct nubus_dir *dir); /* Things to do with directory entries */ -int nubus_get_subdir(const struct nubus_dirent* ent, - struct nubus_dir* dir); +int nubus_get_subdir(const struct nubus_dirent *ent, + struct nubus_dir *dir); void nubus_get_rsrc_mem(void *dest, const struct nubus_dirent *dirent, unsigned int len); void nubus_get_rsrc_str(char *dest, const struct nubus_dirent *dirent, From 883b8cb31a8546b9921c98b255d5f7779d1bc9f6 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sat, 13 Jan 2018 17:37:13 -0500 Subject: [PATCH 10/17] nubus: Generalize block resource handling Scrap the specialized code to unpack video mode name resources and driver resources. It isn't useful. Instead, add a re-usable function to handle lists of block resources of any kind, and descend into the video mode table resource directory. Rename callers as nubus_get_foo(), consistent with their purpose and with related functions in the same file. Tested-by: Stan Johnson Signed-off-by: Finn Thain Signed-off-by: Geert Uytterhoeven --- drivers/nubus/nubus.c | 123 ++++++++++++++++++++++-------------------- 1 file changed, 65 insertions(+), 58 deletions(-) diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c index 4ae5c420f13f..c56ac36d91f2 100644 --- a/drivers/nubus/nubus.c +++ b/drivers/nubus/nubus.c @@ -331,16 +331,63 @@ EXPORT_SYMBOL(nubus_find_rsrc); among other things. The rest of it should go in the /proc code. For now, we just use it to give verbose boot logs. */ -static int __init nubus_show_display_resource(struct nubus_dev *dev, - const struct nubus_dirent *ent) +static int __init nubus_get_block_rsrc_dir(struct nubus_board *board, + const struct nubus_dirent *parent) +{ + struct nubus_dir dir; + struct nubus_dirent ent; + + nubus_get_subdir(parent, &dir); + + while (nubus_readdir(&dir, &ent) != -1) { + u32 size; + + nubus_get_rsrc_mem(&size, &ent, 4); + pr_debug(" block (0x%x), size %d\n", ent.type, size); + } + return 0; +} + +static int __init nubus_get_display_vidmode(struct nubus_board *board, + const struct nubus_dirent *parent) +{ + struct nubus_dir dir; + struct nubus_dirent ent; + + nubus_get_subdir(parent, &dir); + + while (nubus_readdir(&dir, &ent) != -1) { + switch (ent.type) { + case 1: /* mVidParams */ + case 2: /* mTable */ + { + u32 size; + + nubus_get_rsrc_mem(&size, &ent, 4); + pr_debug(" block (0x%x), size %d\n", ent.type, + size); + break; + } + default: + pr_debug(" unknown resource 0x%02x, data 0x%06x\n", + ent.type, ent.data); + } + } + return 0; +} + +static int __init nubus_get_display_resource(struct nubus_dev *dev, + const struct nubus_dirent *ent) { switch (ent->type) { case NUBUS_RESID_GAMMADIR: pr_debug(" gamma directory offset: 0x%06x\n", ent->data); + nubus_get_block_rsrc_dir(dev->board, ent); break; case 0x0080 ... 0x0085: pr_debug(" mode 0x%02x info offset: 0x%06x\n", ent->type, ent->data); + nubus_get_display_vidmode(dev->board, ent); break; default: pr_debug(" unknown resource 0x%02x, data 0x%06x\n", @@ -349,8 +396,8 @@ static int __init nubus_show_display_resource(struct nubus_dev *dev, return 0; } -static int __init nubus_show_network_resource(struct nubus_dev *dev, - const struct nubus_dirent *ent) +static int __init nubus_get_network_resource(struct nubus_dev *dev, + const struct nubus_dirent *ent) { switch (ent->type) { case NUBUS_RESID_MAC_ADDRESS: @@ -368,8 +415,8 @@ static int __init nubus_show_network_resource(struct nubus_dev *dev, return 0; } -static int __init nubus_show_cpu_resource(struct nubus_dev *dev, - const struct nubus_dirent *ent) +static int __init nubus_get_cpu_resource(struct nubus_dev *dev, + const struct nubus_dirent *ent) { switch (ent->type) { case NUBUS_RESID_MEMINFO: @@ -397,18 +444,18 @@ static int __init nubus_show_cpu_resource(struct nubus_dev *dev, return 0; } -static int __init nubus_show_private_resource(struct nubus_dev *dev, - const struct nubus_dirent *ent) +static int __init nubus_get_private_resource(struct nubus_dev *dev, + const struct nubus_dirent *ent) { switch (dev->category) { case NUBUS_CAT_DISPLAY: - nubus_show_display_resource(dev, ent); + nubus_get_display_resource(dev, ent); break; case NUBUS_CAT_NETWORK: - nubus_show_network_resource(dev, ent); + nubus_get_network_resource(dev, ent); break; case NUBUS_CAT_CPU: - nubus_show_cpu_resource(dev, ent); + nubus_get_cpu_resource(dev, ent); break; default: pr_debug(" unknown resource 0x%02x, data 0x%06x\n", @@ -462,14 +509,9 @@ nubus_get_functional_resource(struct nubus_board *board, int slot, { /* MacOS driver. If we were NetBSD we might use this :-) */ - struct nubus_dir drvr_dir; - struct nubus_dirent drvr_ent; - unsigned char *driver; - - nubus_get_subdir(&ent, &drvr_dir); - nubus_readdir(&drvr_dir, &drvr_ent); - driver = nubus_dirptr(&drvr_ent); - pr_debug(" driver at: 0x%p\n", driver); + pr_debug(" driver directory offset: 0x%06x\n", + ent.data); + nubus_get_block_rsrc_dir(board, &ent); break; } case NUBUS_RESID_MINOR_BASEOS: @@ -501,50 +543,13 @@ nubus_get_functional_resource(struct nubus_board *board, int slot, default: /* Local/Private resources have their own function */ - nubus_show_private_resource(dev, &ent); + nubus_get_private_resource(dev, &ent); } } return dev; } -/* This is cool. */ -static int __init nubus_get_vidnames(struct nubus_board *board, - const struct nubus_dirent *parent) -{ - struct nubus_dir dir; - struct nubus_dirent ent; - - /* FIXME: obviously we want to put this in a header file soon */ - struct vidmode { - u32 size; - /* Don't know what this is yet */ - u16 id; - /* Longest one I've seen so far is 26 characters */ - char name[36]; - }; - - pr_debug(" video modes supported:\n"); - nubus_get_subdir(parent, &dir); - - while (nubus_readdir(&dir, &ent) != -1) { - struct vidmode mode; - u32 size; - - /* First get the length */ - nubus_get_rsrc_mem(&size, &ent, 4); - - /* Now clobber the whole thing */ - if (size > sizeof(mode) - 1) - size = sizeof(mode) - 1; - memset(&mode, 0, sizeof(mode)); - nubus_get_rsrc_mem(&mode, &ent, size); - pr_debug(" 0x%02x: 0x%04x %s\n", ent.type, - mode.id, mode.name); - } - return 0; -} - /* This is *really* cool. */ static int __init nubus_get_icon(struct nubus_board *board, const struct nubus_dirent *ent) @@ -641,7 +646,9 @@ static int __init nubus_get_board_resource(struct nubus_board *board, int slot, break; /* WTF isn't this in the functional resources? */ case NUBUS_RESID_VIDNAMES: - nubus_get_vidnames(board, &ent); + pr_debug(" vidnames directory offset: 0x%06x\n", + ent.data); + nubus_get_block_rsrc_dir(board, &ent); break; /* Same goes for this */ case NUBUS_RESID_VIDMODES: From 2f7dd07ecadac6bdc3d55c217d65efa2834ba1cb Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sat, 13 Jan 2018 17:37:13 -0500 Subject: [PATCH 11/17] nubus: Rework /proc/bus/nubus/s/ implementation The /proc/bus/nubus/s/ directory tree for any slot s is missing a lot of information. The struct file_operations methods have long been left unimplemented (hence the familiar compile-time warning, "Need to set some I/O handlers here"). Slot resources have a complex structure which varies depending on board function. The logic for interpreting these ROM data structures is found in nubus.c. Let's not duplicate that logic in proc.c. Create the /proc/bus/nubus/s/ inodes while scanning slot s. During descent through slot resource subdirectories, call the new nubus_proc_add_foo() functions to create the procfs inodes. Also add a new function, nubus_seq_write_rsrc_mem(), to write the contents of a particular slot resource to a given seq_file. This is used by the procfs file_operations methods, to finally give userspace access to slot ROM information, such as the available video modes. Tested-by: Stan Johnson Signed-off-by: Finn Thain Signed-off-by: Geert Uytterhoeven --- drivers/nubus/nubus.c | 114 ++++++++++++++++----- drivers/nubus/proc.c | 226 +++++++++++++++++++++++++----------------- include/linux/nubus.h | 37 ++++++- 3 files changed, 258 insertions(+), 119 deletions(-) diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c index c56ac36d91f2..f05541914c21 100644 --- a/drivers/nubus/nubus.c +++ b/drivers/nubus/nubus.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -146,7 +147,7 @@ static inline void *nubus_rom_addr(int slot) return (void *)(0xF1000000 + (slot << 24)); } -static unsigned char *nubus_dirptr(const struct nubus_dirent *nd) +unsigned char *nubus_dirptr(const struct nubus_dirent *nd) { unsigned char *p = nd->base; @@ -173,8 +174,8 @@ void nubus_get_rsrc_mem(void *dest, const struct nubus_dirent *dirent, } EXPORT_SYMBOL(nubus_get_rsrc_mem); -void nubus_get_rsrc_str(char *dest, const struct nubus_dirent *dirent, - unsigned int len) +unsigned int nubus_get_rsrc_str(char *dest, const struct nubus_dirent *dirent, + unsigned int len) { char *t = dest; unsigned char *p = nubus_dirptr(dirent); @@ -189,9 +190,33 @@ void nubus_get_rsrc_str(char *dest, const struct nubus_dirent *dirent, } if (len > 0) *t = '\0'; + return t - dest; } EXPORT_SYMBOL(nubus_get_rsrc_str); +void nubus_seq_write_rsrc_mem(struct seq_file *m, + const struct nubus_dirent *dirent, + unsigned int len) +{ + unsigned long buf[32]; + unsigned int buf_size = sizeof(buf); + unsigned char *p = nubus_dirptr(dirent); + + /* If possible, write out full buffers */ + while (len >= buf_size) { + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(buf); i++) + buf[i] = nubus_get_rom(&p, sizeof(buf[0]), + dirent->mask); + seq_write(m, buf, buf_size); + len -= buf_size; + } + /* If not, write out individual bytes */ + while (len--) + seq_putc(m, nubus_get_rom(&p, 1, dirent->mask)); +} + int nubus_get_root_dir(const struct nubus_board *board, struct nubus_dir *dir) { @@ -326,35 +351,35 @@ EXPORT_SYMBOL(nubus_find_rsrc); looking at, and print out lots and lots of information from the resource blocks. */ -/* FIXME: A lot of this stuff will eventually be useful after - initialization, for intelligently probing Ethernet and video chips, - among other things. The rest of it should go in the /proc code. - For now, we just use it to give verbose boot logs. */ - static int __init nubus_get_block_rsrc_dir(struct nubus_board *board, + struct proc_dir_entry *procdir, const struct nubus_dirent *parent) { struct nubus_dir dir; struct nubus_dirent ent; nubus_get_subdir(parent, &dir); + dir.procdir = nubus_proc_add_rsrc_dir(procdir, parent, board); while (nubus_readdir(&dir, &ent) != -1) { u32 size; nubus_get_rsrc_mem(&size, &ent, 4); pr_debug(" block (0x%x), size %d\n", ent.type, size); + nubus_proc_add_rsrc_mem(dir.procdir, &ent, size); } return 0; } static int __init nubus_get_display_vidmode(struct nubus_board *board, + struct proc_dir_entry *procdir, const struct nubus_dirent *parent) { struct nubus_dir dir; struct nubus_dirent ent; nubus_get_subdir(parent, &dir); + dir.procdir = nubus_proc_add_rsrc_dir(procdir, parent, board); while (nubus_readdir(&dir, &ent) != -1) { switch (ent.type) { @@ -366,37 +391,42 @@ static int __init nubus_get_display_vidmode(struct nubus_board *board, nubus_get_rsrc_mem(&size, &ent, 4); pr_debug(" block (0x%x), size %d\n", ent.type, size); + nubus_proc_add_rsrc_mem(dir.procdir, &ent, size); break; } default: pr_debug(" unknown resource 0x%02x, data 0x%06x\n", ent.type, ent.data); + nubus_proc_add_rsrc_mem(dir.procdir, &ent, 0); } } return 0; } static int __init nubus_get_display_resource(struct nubus_dev *dev, + struct proc_dir_entry *procdir, const struct nubus_dirent *ent) { switch (ent->type) { case NUBUS_RESID_GAMMADIR: pr_debug(" gamma directory offset: 0x%06x\n", ent->data); - nubus_get_block_rsrc_dir(dev->board, ent); + nubus_get_block_rsrc_dir(dev->board, procdir, ent); break; case 0x0080 ... 0x0085: pr_debug(" mode 0x%02x info offset: 0x%06x\n", ent->type, ent->data); - nubus_get_display_vidmode(dev->board, ent); + nubus_get_display_vidmode(dev->board, procdir, ent); break; default: pr_debug(" unknown resource 0x%02x, data 0x%06x\n", ent->type, ent->data); + nubus_proc_add_rsrc_mem(procdir, ent, 0); } return 0; } static int __init nubus_get_network_resource(struct nubus_dev *dev, + struct proc_dir_entry *procdir, const struct nubus_dirent *ent) { switch (ent->type) { @@ -406,16 +436,19 @@ static int __init nubus_get_network_resource(struct nubus_dev *dev, nubus_get_rsrc_mem(addr, ent, 6); pr_debug(" MAC address: %pM\n", addr); + nubus_proc_add_rsrc_mem(procdir, ent, 6); break; } default: pr_debug(" unknown resource 0x%02x, data 0x%06x\n", ent->type, ent->data); + nubus_proc_add_rsrc_mem(procdir, ent, 0); } return 0; } static int __init nubus_get_cpu_resource(struct nubus_dev *dev, + struct proc_dir_entry *procdir, const struct nubus_dirent *ent) { switch (ent->type) { @@ -426,6 +459,7 @@ static int __init nubus_get_cpu_resource(struct nubus_dev *dev, nubus_get_rsrc_mem(&meminfo, ent, 8); pr_debug(" memory: [ 0x%08lx 0x%08lx ]\n", meminfo[0], meminfo[1]); + nubus_proc_add_rsrc_mem(procdir, ent, 8); break; } case NUBUS_RESID_ROMINFO: @@ -435,31 +469,35 @@ static int __init nubus_get_cpu_resource(struct nubus_dev *dev, nubus_get_rsrc_mem(&rominfo, ent, 8); pr_debug(" ROM: [ 0x%08lx 0x%08lx ]\n", rominfo[0], rominfo[1]); + nubus_proc_add_rsrc_mem(procdir, ent, 8); break; } default: pr_debug(" unknown resource 0x%02x, data 0x%06x\n", ent->type, ent->data); + nubus_proc_add_rsrc_mem(procdir, ent, 0); } return 0; } static int __init nubus_get_private_resource(struct nubus_dev *dev, + struct proc_dir_entry *procdir, const struct nubus_dirent *ent) { switch (dev->category) { case NUBUS_CAT_DISPLAY: - nubus_get_display_resource(dev, ent); + nubus_get_display_resource(dev, procdir, ent); break; case NUBUS_CAT_NETWORK: - nubus_get_network_resource(dev, ent); + nubus_get_network_resource(dev, procdir, ent); break; case NUBUS_CAT_CPU: - nubus_get_cpu_resource(dev, ent); + nubus_get_cpu_resource(dev, procdir, ent); break; default: pr_debug(" unknown resource 0x%02x, data 0x%06x\n", ent->type, ent->data); + nubus_proc_add_rsrc_mem(procdir, ent, 0); } return 0; } @@ -474,6 +512,7 @@ nubus_get_functional_resource(struct nubus_board *board, int slot, pr_debug(" Functional resource 0x%02x:\n", parent->type); nubus_get_subdir(parent, &dir); + dir.procdir = nubus_proc_add_rsrc_dir(board->procdir, parent, board); /* Actually we should probably panic if this fails */ if ((dev = kzalloc(sizeof(*dev), GFP_ATOMIC)) == NULL) @@ -495,14 +534,17 @@ nubus_get_functional_resource(struct nubus_board *board, int slot, dev->dr_hw = nbtdata[3]; pr_debug(" type: [cat 0x%x type 0x%x sw 0x%x hw 0x%x]\n", nbtdata[0], nbtdata[1], nbtdata[2], nbtdata[3]); + nubus_proc_add_rsrc_mem(dir.procdir, &ent, 8); break; } case NUBUS_RESID_NAME: { char name[64]; + unsigned int len; - nubus_get_rsrc_str(name, &ent, sizeof(name)); + len = nubus_get_rsrc_str(name, &ent, sizeof(name)); pr_debug(" name: %s\n", name); + nubus_proc_add_rsrc_mem(dir.procdir, &ent, len + 1); break; } case NUBUS_RESID_DRVRDIR: @@ -511,7 +553,7 @@ nubus_get_functional_resource(struct nubus_board *board, int slot, use this :-) */ pr_debug(" driver directory offset: 0x%06x\n", ent.data); - nubus_get_block_rsrc_dir(board, &ent); + nubus_get_block_rsrc_dir(board, dir.procdir, &ent); break; } case NUBUS_RESID_MINOR_BASEOS: @@ -523,6 +565,7 @@ nubus_get_functional_resource(struct nubus_board *board, int slot, nubus_get_rsrc_mem(&base_offset, &ent, 4); pr_debug(" memory offset: 0x%08x\n", base_offset); + nubus_proc_add_rsrc_mem(dir.procdir, &ent, 4); break; } case NUBUS_RESID_MINOR_LENGTH: @@ -532,18 +575,21 @@ nubus_get_functional_resource(struct nubus_board *board, int slot, nubus_get_rsrc_mem(&length, &ent, 4); pr_debug(" memory length: 0x%08x\n", length); + nubus_proc_add_rsrc_mem(dir.procdir, &ent, 4); break; } case NUBUS_RESID_FLAGS: pr_debug(" flags: 0x%06x\n", ent.data); + nubus_proc_add_rsrc(dir.procdir, &ent); break; case NUBUS_RESID_HWDEVID: pr_debug(" hwdevid: 0x%06x\n", ent.data); + nubus_proc_add_rsrc(dir.procdir, &ent); break; default: /* Local/Private resources have their own function */ - nubus_get_private_resource(dev, &ent); + nubus_get_private_resource(dev, dir.procdir, &ent); } } @@ -552,6 +598,7 @@ nubus_get_functional_resource(struct nubus_board *board, int slot, /* This is *really* cool. */ static int __init nubus_get_icon(struct nubus_board *board, + struct proc_dir_entry *procdir, const struct nubus_dirent *ent) { /* Should be 32x32 if my memory serves me correctly */ @@ -564,11 +611,13 @@ static int __init nubus_get_icon(struct nubus_board *board, pr_debug(" %08x %08x %08x %08x\n", icon[i * 4 + 0], icon[i * 4 + 1], icon[i * 4 + 2], icon[i * 4 + 3]); + nubus_proc_add_rsrc_mem(procdir, ent, 128); return 0; } static int __init nubus_get_vendorinfo(struct nubus_board *board, + struct proc_dir_entry *procdir, const struct nubus_dirent *parent) { struct nubus_dir dir; @@ -578,15 +627,18 @@ static int __init nubus_get_vendorinfo(struct nubus_board *board, pr_debug(" vendor info:\n"); nubus_get_subdir(parent, &dir); + dir.procdir = nubus_proc_add_rsrc_dir(procdir, parent, board); while (nubus_readdir(&dir, &ent) != -1) { char name[64]; + unsigned int len; /* These are all strings, we think */ - nubus_get_rsrc_str(name, &ent, sizeof(name)); + len = nubus_get_rsrc_str(name, &ent, sizeof(name)); if (ent.type < 1 || ent.type > 5) ent.type = 5; pr_debug(" %s: %s\n", vendor_fields[ent.type - 1], name); + nubus_proc_add_rsrc_mem(dir.procdir, &ent, len + 1); } return 0; } @@ -599,6 +651,7 @@ static int __init nubus_get_board_resource(struct nubus_board *board, int slot, pr_debug(" Board resource 0x%02x:\n", parent->type); nubus_get_subdir(parent, &dir); + dir.procdir = nubus_proc_add_rsrc_dir(board->procdir, parent, board); while (nubus_readdir(&dir, &ent) != -1) { switch (ent.type) { @@ -615,49 +668,62 @@ static int __init nubus_get_board_resource(struct nubus_board *board, int slot, nbtdata[2] != 0 || nbtdata[3] != 0) pr_err("Slot %X: sResource is not a board resource!\n", slot); + nubus_proc_add_rsrc_mem(dir.procdir, &ent, 8); break; } case NUBUS_RESID_NAME: - nubus_get_rsrc_str(board->name, &ent, - sizeof(board->name)); + { + unsigned int len; + + len = nubus_get_rsrc_str(board->name, &ent, + sizeof(board->name)); pr_debug(" name: %s\n", board->name); + nubus_proc_add_rsrc_mem(dir.procdir, &ent, len + 1); break; + } case NUBUS_RESID_ICON: - nubus_get_icon(board, &ent); + nubus_get_icon(board, dir.procdir, &ent); break; case NUBUS_RESID_BOARDID: pr_debug(" board id: 0x%x\n", ent.data); + nubus_proc_add_rsrc(dir.procdir, &ent); break; case NUBUS_RESID_PRIMARYINIT: pr_debug(" primary init offset: 0x%06x\n", ent.data); + nubus_proc_add_rsrc(dir.procdir, &ent); break; case NUBUS_RESID_VENDORINFO: - nubus_get_vendorinfo(board, &ent); + nubus_get_vendorinfo(board, dir.procdir, &ent); break; case NUBUS_RESID_FLAGS: pr_debug(" flags: 0x%06x\n", ent.data); + nubus_proc_add_rsrc(dir.procdir, &ent); break; case NUBUS_RESID_HWDEVID: pr_debug(" hwdevid: 0x%06x\n", ent.data); + nubus_proc_add_rsrc(dir.procdir, &ent); break; case NUBUS_RESID_SECONDINIT: pr_debug(" secondary init offset: 0x%06x\n", ent.data); + nubus_proc_add_rsrc(dir.procdir, &ent); break; /* WTF isn't this in the functional resources? */ case NUBUS_RESID_VIDNAMES: pr_debug(" vidnames directory offset: 0x%06x\n", ent.data); - nubus_get_block_rsrc_dir(board, &ent); + nubus_get_block_rsrc_dir(board, dir.procdir, &ent); break; /* Same goes for this */ case NUBUS_RESID_VIDMODES: pr_debug(" video mode parameter directory offset: 0x%06x\n", ent.data); + nubus_proc_add_rsrc(dir.procdir, &ent); break; default: pr_debug(" unknown resource 0x%02x, data 0x%06x\n", ent.type, ent.data); + nubus_proc_add_rsrc_mem(dir.procdir, &ent, 0); } } return 0; @@ -748,6 +814,8 @@ static struct nubus_board * __init nubus_add_board(int slot, int bytelanes) if (ent.type < 1 || ent.type > 127) pr_warn("Slot %X: Board resource ID is invalid!\n", slot); + board->procdir = nubus_proc_add_board(board); + nubus_get_board_resource(board, slot, &ent); while (nubus_readdir(&dir, &ent) != -1) { @@ -835,8 +903,8 @@ static int __init nubus_init(void) if (!MACH_IS_MAC) return 0; - nubus_scan_bus(); nubus_proc_init(); + nubus_scan_bus(); return 0; } diff --git a/drivers/nubus/proc.c b/drivers/nubus/proc.c index 41ec859bdd8b..f47d90924ab4 100644 --- a/drivers/nubus/proc.c +++ b/drivers/nubus/proc.c @@ -11,24 +11,28 @@ structure in /proc analogous to the structure of the NuBus ROM resources. - Therefore each NuBus device is in fact a directory, which may in - turn contain subdirectories. The "files" correspond to NuBus - resource records. For those types of records which we know how to - convert to formats that are meaningful to userspace (mostly just - icons) these files will provide "cooked" data. Otherwise they will - simply provide raw access (read-only of course) to the ROM. */ + Therefore each board function gets a directory, which may in turn + contain subdirectories. Each slot resource is a file. Unrecognized + resources are empty files, since every resource ID requires a special + case (e.g. if the resource ID implies a directory or block, then its + value has to be interpreted as a slot ROM pointer etc.). + */ #include #include #include #include #include +#include #include #include - #include #include +/* + * /proc/bus/nubus/devices stuff + */ + static int nubus_devices_proc_show(struct seq_file *m, void *v) { @@ -61,96 +65,141 @@ static const struct file_operations nubus_devices_proc_fops = { static struct proc_dir_entry *proc_bus_nubus_dir; -static const struct file_operations nubus_proc_subdir_fops = { -#warning Need to set some I/O handlers here +/* + * /proc/bus/nubus/x/ stuff + */ + +struct proc_dir_entry *nubus_proc_add_board(struct nubus_board *board) +{ + char name[2]; + + if (!proc_bus_nubus_dir) + return NULL; + snprintf(name, sizeof(name), "%x", board->slot); + return proc_mkdir(name, proc_bus_nubus_dir); +} + +/* The PDE private data for any directory under /proc/bus/nubus/x/ + * is the bytelanes value for the board in slot x. + */ + +struct proc_dir_entry *nubus_proc_add_rsrc_dir(struct proc_dir_entry *procdir, + const struct nubus_dirent *ent, + struct nubus_board *board) +{ + char name[9]; + int lanes = board->lanes; + + if (!procdir) + return NULL; + snprintf(name, sizeof(name), "%x", ent->type); + return proc_mkdir_data(name, 0555, procdir, (void *)lanes); +} + +/* The PDE private data for a file under /proc/bus/nubus/x/ is a pointer to + * an instance of the following structure, which gives the location and size + * of the resource data in the slot ROM. For slot resources which hold only a + * small integer, this integer value is stored directly and size is set to 0. + * A NULL private data pointer indicates an unrecognized resource. + */ + +struct nubus_proc_pde_data { + unsigned char *res_ptr; + unsigned int res_size; }; -static void nubus_proc_subdir(struct nubus_dev* dev, - struct proc_dir_entry* parent, - struct nubus_dir* dir) +static struct nubus_proc_pde_data * +nubus_proc_alloc_pde_data(unsigned char *ptr, unsigned int size) { - struct nubus_dirent ent; + struct nubus_proc_pde_data *pde_data; - /* Some of these are directories, others aren't */ - while (nubus_readdir(dir, &ent) != -1) { - char name[9]; - struct proc_dir_entry* e; - - snprintf(name, sizeof(name), "%x", ent.type); - e = proc_create(name, S_IFREG | S_IRUGO | S_IWUSR, parent, - &nubus_proc_subdir_fops); - if (!e) - return; - } + pde_data = kmalloc(sizeof(*pde_data), GFP_KERNEL); + if (!pde_data) + return NULL; + + pde_data->res_ptr = ptr; + pde_data->res_size = size; + return pde_data; } -/* Can't do this recursively since the root directory is structured - somewhat differently from the subdirectories */ -static void nubus_proc_populate(struct nubus_dev* dev, - struct proc_dir_entry* parent, - struct nubus_dir* root) +static int nubus_proc_rsrc_show(struct seq_file *m, void *v) { - struct nubus_dirent ent; + struct inode *inode = m->private; + struct nubus_proc_pde_data *pde_data; - /* We know these are all directories (board resource + one or - more functional resources) */ - while (nubus_readdir(root, &ent) != -1) { - char name[9]; - struct proc_dir_entry* e; - struct nubus_dir dir; - - snprintf(name, sizeof(name), "%x", ent.type); - e = proc_mkdir(name, parent); - if (!e) return; - - /* And descend */ - if (nubus_get_subdir(&ent, &dir) == -1) { - /* This shouldn't happen */ - printk(KERN_ERR "NuBus root directory node %x:%x has no subdir!\n", - dev->board->slot, ent.type); - continue; - } else { - nubus_proc_subdir(dev, e, &dir); - } - } -} - -int nubus_proc_attach_device(struct nubus_dev *dev) -{ - struct proc_dir_entry *e; - struct nubus_dir root; - char name[9]; - - if (dev == NULL) { - printk(KERN_ERR - "NULL pointer in nubus_proc_attach_device, shoot the programmer!\n"); - return -1; - } - - if (dev->board == NULL) { - printk(KERN_ERR - "NULL pointer in nubus_proc_attach_device, shoot the programmer!\n"); - printk("dev = %p, dev->board = %p\n", dev, dev->board); - return -1; - } - - if (dev->board->procdir) + pde_data = PDE_DATA(inode); + if (!pde_data) return 0; - /* Create a directory */ - snprintf(name, sizeof(name), "%x", dev->board->slot); - e = proc_mkdir(name, proc_bus_nubus_dir); - dev->board->procdir = e; - if (!e) - return -ENOMEM; + if (pde_data->res_size > m->size) + return -EFBIG; - /* Now recursively populate it with files */ - nubus_get_root_dir(dev->board, &root); - nubus_proc_populate(dev, e, &root); + if (pde_data->res_size) { + int lanes = (int)proc_get_parent_data(inode); + struct nubus_dirent ent; + if (!lanes) + return 0; + + ent.mask = lanes; + ent.base = pde_data->res_ptr; + ent.data = 0; + nubus_seq_write_rsrc_mem(m, &ent, pde_data->res_size); + } else { + unsigned int data = (unsigned int)pde_data->res_ptr; + + seq_putc(m, data >> 16); + seq_putc(m, data >> 8); + seq_putc(m, data >> 0); + } return 0; } -EXPORT_SYMBOL(nubus_proc_attach_device); + +static int nubus_proc_rsrc_open(struct inode *inode, struct file *file) +{ + return single_open(file, nubus_proc_rsrc_show, inode); +} + +static const struct file_operations nubus_proc_rsrc_fops = { + .open = nubus_proc_rsrc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +void nubus_proc_add_rsrc_mem(struct proc_dir_entry *procdir, + const struct nubus_dirent *ent, + unsigned int size) +{ + char name[9]; + struct nubus_proc_pde_data *pde_data; + + if (!procdir) + return; + + snprintf(name, sizeof(name), "%x", ent->type); + if (size) + pde_data = nubus_proc_alloc_pde_data(nubus_dirptr(ent), size); + else + pde_data = NULL; + proc_create_data(name, S_IFREG | 0444, procdir, + &nubus_proc_rsrc_fops, pde_data); +} + +void nubus_proc_add_rsrc(struct proc_dir_entry *procdir, + const struct nubus_dirent *ent) +{ + char name[9]; + unsigned char *data = (unsigned char *)ent->data; + + if (!procdir) + return; + + snprintf(name, sizeof(name), "%x", ent->type); + proc_create_data(name, S_IFREG | 0444, procdir, + &nubus_proc_rsrc_fops, + nubus_proc_alloc_pde_data(data, 0)); +} /* * /proc/nubus stuff @@ -219,18 +268,11 @@ static const struct file_operations nubus_proc_fops = { .release = seq_release, }; -void __init proc_bus_nubus_add_devices(void) -{ - struct nubus_dev *dev; - - for(dev = nubus_devices; dev; dev = dev->next) - nubus_proc_attach_device(dev); -} - void __init nubus_proc_init(void) { proc_create("nubus", 0, NULL, &nubus_proc_fops); proc_bus_nubus_dir = proc_mkdir("bus/nubus", NULL); + if (!proc_bus_nubus_dir) + return; proc_create("devices", 0, proc_bus_nubus_dir, &nubus_devices_proc_fops); - proc_bus_nubus_add_devices(); } diff --git a/include/linux/nubus.h b/include/linux/nubus.h index 2d6f04055ebe..0a9e08e76606 100644 --- a/include/linux/nubus.h +++ b/include/linux/nubus.h @@ -13,11 +13,15 @@ #include #include +struct proc_dir_entry; +struct seq_file; + struct nubus_dir { unsigned char *base; unsigned char *ptr; int done; int mask; + struct proc_dir_entry *procdir; }; struct nubus_dirent { @@ -84,12 +88,33 @@ extern struct nubus_board *nubus_boards; /* Generic NuBus interface functions, modelled after the PCI interface */ #ifdef CONFIG_PROC_FS -extern void nubus_proc_init(void); +void nubus_proc_init(void); +struct proc_dir_entry *nubus_proc_add_board(struct nubus_board *board); +struct proc_dir_entry *nubus_proc_add_rsrc_dir(struct proc_dir_entry *procdir, + const struct nubus_dirent *ent, + struct nubus_board *board); +void nubus_proc_add_rsrc_mem(struct proc_dir_entry *procdir, + const struct nubus_dirent *ent, + unsigned int size); +void nubus_proc_add_rsrc(struct proc_dir_entry *procdir, + const struct nubus_dirent *ent); #else static inline void nubus_proc_init(void) {} +static inline +struct proc_dir_entry *nubus_proc_add_board(struct nubus_board *board) +{ return NULL; } +static inline +struct proc_dir_entry *nubus_proc_add_rsrc_dir(struct proc_dir_entry *procdir, + const struct nubus_dirent *ent, + struct nubus_board *board) +{ return NULL; } +static inline void nubus_proc_add_rsrc_mem(struct proc_dir_entry *procdir, + const struct nubus_dirent *ent, + unsigned int size) {} +static inline void nubus_proc_add_rsrc(struct proc_dir_entry *procdir, + const struct nubus_dirent *ent) {} #endif -int nubus_proc_attach_device(struct nubus_dev *dev); /* If we need more precision we can add some more of these */ struct nubus_dev *nubus_find_type(unsigned short category, unsigned short type, @@ -125,8 +150,12 @@ int nubus_get_subdir(const struct nubus_dirent *ent, struct nubus_dir *dir); void nubus_get_rsrc_mem(void *dest, const struct nubus_dirent *dirent, unsigned int len); -void nubus_get_rsrc_str(char *dest, const struct nubus_dirent *dirent, - unsigned int maxlen); +unsigned int nubus_get_rsrc_str(char *dest, const struct nubus_dirent *dirent, + unsigned int len); +void nubus_seq_write_rsrc_mem(struct seq_file *m, + const struct nubus_dirent *dirent, + unsigned int len); +unsigned char *nubus_dirptr(const struct nubus_dirent *nd); /* Returns a pointer to the "standard" slot space. */ static inline void *nubus_slot_addr(int slot) From 189e19e8cbb49f5bf483e55bdbd1e56d3d6bcf75 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sat, 13 Jan 2018 17:37:13 -0500 Subject: [PATCH 12/17] nubus: Rename struct nubus_dev It is misleading to call a functional resource a "device". In adopting the Linux Driver Model, the struct device will be embedded in struct nubus_board. That will compound the terminlogy problem because drivers will bind with boards, not with functional resources. Avoid this by renaming struct nubus_dev as struct nubus_rsrc. "Functional resource" is the vendor's terminology so this helps avoid confusion. Cc: "David S. Miller" Cc: Bartlomiej Zolnierkiewicz Acked-by: Bartlomiej Zolnierkiewicz Tested-by: Stan Johnson Signed-off-by: Finn Thain Signed-off-by: Geert Uytterhoeven --- drivers/net/ethernet/8390/mac8390.c | 26 +++--- drivers/net/ethernet/natsemi/macsonic.c | 22 ++--- drivers/nubus/nubus.c | 105 ++++++++++++------------ drivers/nubus/proc.c | 15 ++-- drivers/video/fbdev/macfb.c | 2 +- include/linux/nubus.h | 30 ++++--- 6 files changed, 98 insertions(+), 102 deletions(-) diff --git a/drivers/net/ethernet/8390/mac8390.c b/drivers/net/ethernet/8390/mac8390.c index 9497f18eaba0..929ff6419621 100644 --- a/drivers/net/ethernet/8390/mac8390.c +++ b/drivers/net/ethernet/8390/mac8390.c @@ -123,7 +123,8 @@ enum mac8390_access { }; extern int mac8390_memtest(struct net_device *dev); -static int mac8390_initdev(struct net_device *dev, struct nubus_dev *ndev, +static int mac8390_initdev(struct net_device *dev, + struct nubus_rsrc *ndev, enum mac8390_type type); static int mac8390_open(struct net_device *dev); @@ -169,11 +170,11 @@ static void word_memcpy_tocard(unsigned long tp, const void *fp, int count); static void word_memcpy_fromcard(void *tp, unsigned long fp, int count); static u32 mac8390_msg_enable; -static enum mac8390_type __init mac8390_ident(struct nubus_dev *dev) +static enum mac8390_type __init mac8390_ident(struct nubus_rsrc *fres) { - switch (dev->dr_sw) { + switch (fres->dr_sw) { case NUBUS_DRSW_3COM: - switch (dev->dr_hw) { + switch (fres->dr_hw) { case NUBUS_DRHW_APPLE_SONIC_NB: case NUBUS_DRHW_APPLE_SONIC_LC: case NUBUS_DRHW_SONNET: @@ -184,7 +185,7 @@ static enum mac8390_type __init mac8390_ident(struct nubus_dev *dev) break; case NUBUS_DRSW_APPLE: - switch (dev->dr_hw) { + switch (fres->dr_hw) { case NUBUS_DRHW_ASANTE_LC: return MAC8390_NONE; case NUBUS_DRHW_CABLETRON: @@ -201,7 +202,7 @@ static enum mac8390_type __init mac8390_ident(struct nubus_dev *dev) case NUBUS_DRSW_TECHWORKS: case NUBUS_DRSW_DAYNA2: case NUBUS_DRSW_DAYNA_LC: - if (dev->dr_hw == NUBUS_DRHW_CABLETRON) + if (fres->dr_hw == NUBUS_DRHW_CABLETRON) return MAC8390_CABLETRON; else return MAC8390_APPLE; @@ -212,7 +213,7 @@ static enum mac8390_type __init mac8390_ident(struct nubus_dev *dev) break; case NUBUS_DRSW_KINETICS: - switch (dev->dr_hw) { + switch (fres->dr_hw) { case NUBUS_DRHW_INTERLAN: return MAC8390_INTERLAN; default: @@ -225,8 +226,8 @@ static enum mac8390_type __init mac8390_ident(struct nubus_dev *dev) * These correspond to Dayna Sonic cards * which use the macsonic driver */ - if (dev->dr_hw == NUBUS_DRHW_SMC9194 || - dev->dr_hw == NUBUS_DRHW_INTERLAN) + if (fres->dr_hw == NUBUS_DRHW_SMC9194 || + fres->dr_hw == NUBUS_DRHW_INTERLAN) return MAC8390_NONE; else return MAC8390_DAYNA; @@ -289,7 +290,8 @@ static int __init mac8390_memsize(unsigned long membase) return i * 0x1000; } -static bool __init mac8390_init(struct net_device *dev, struct nubus_dev *ndev, +static bool __init mac8390_init(struct net_device *dev, + struct nubus_rsrc *ndev, enum mac8390_type cardtype) { struct nubus_dir dir; @@ -394,7 +396,7 @@ static bool __init mac8390_init(struct net_device *dev, struct nubus_dev *ndev, struct net_device * __init mac8390_probe(int unit) { struct net_device *dev; - struct nubus_dev *ndev = NULL; + struct nubus_rsrc *ndev = NULL; int err = -ENODEV; struct ei_device *ei_local; @@ -489,7 +491,7 @@ static const struct net_device_ops mac8390_netdev_ops = { }; static int __init mac8390_initdev(struct net_device *dev, - struct nubus_dev *ndev, + struct nubus_rsrc *ndev, enum mac8390_type type) { static u32 fwrd4_offsets[16] = { diff --git a/drivers/net/ethernet/natsemi/macsonic.c b/drivers/net/ethernet/natsemi/macsonic.c index a42433fb6949..14f3fb50dc21 100644 --- a/drivers/net/ethernet/natsemi/macsonic.c +++ b/drivers/net/ethernet/natsemi/macsonic.c @@ -428,26 +428,26 @@ static int mac_nubus_sonic_ethernet_addr(struct net_device *dev, return 0; } -static int macsonic_ident(struct nubus_dev *ndev) +static int macsonic_ident(struct nubus_rsrc *fres) { - if (ndev->dr_hw == NUBUS_DRHW_ASANTE_LC && - ndev->dr_sw == NUBUS_DRSW_SONIC_LC) + if (fres->dr_hw == NUBUS_DRHW_ASANTE_LC && + fres->dr_sw == NUBUS_DRSW_SONIC_LC) return MACSONIC_DAYNALINK; - if (ndev->dr_hw == NUBUS_DRHW_SONIC && - ndev->dr_sw == NUBUS_DRSW_APPLE) { + if (fres->dr_hw == NUBUS_DRHW_SONIC && + fres->dr_sw == NUBUS_DRSW_APPLE) { /* There has to be a better way to do this... */ - if (strstr(ndev->board->name, "DuoDock")) + if (strstr(fres->board->name, "DuoDock")) return MACSONIC_DUODOCK; else return MACSONIC_APPLE; } - if (ndev->dr_hw == NUBUS_DRHW_SMC9194 && - ndev->dr_sw == NUBUS_DRSW_DAYNA) + if (fres->dr_hw == NUBUS_DRHW_SMC9194 && + fres->dr_sw == NUBUS_DRSW_DAYNA) return MACSONIC_DAYNA; - if (ndev->dr_hw == NUBUS_DRHW_APPLE_SONIC_LC && - ndev->dr_sw == 0) { /* huh? */ + if (fres->dr_hw == NUBUS_DRHW_APPLE_SONIC_LC && + fres->dr_sw == 0) { /* huh? */ return MACSONIC_APPLE16; } return -1; @@ -456,7 +456,7 @@ static int macsonic_ident(struct nubus_dev *ndev) static int mac_nubus_sonic_probe(struct net_device *dev) { static int slots; - struct nubus_dev* ndev = NULL; + struct nubus_rsrc *ndev = NULL; struct sonic_local* lp = netdev_priv(dev); unsigned long base_addr, prom_addr; u16 sonic_dcr; diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c index f05541914c21..3657b13c0022 100644 --- a/drivers/nubus/nubus.c +++ b/drivers/nubus/nubus.c @@ -32,7 +32,7 @@ /* Globals */ -struct nubus_dev *nubus_devices; +struct nubus_rsrc *nubus_func_rsrcs; struct nubus_board *nubus_boards; /* Meaning of "bytelanes": @@ -228,12 +228,11 @@ int nubus_get_root_dir(const struct nubus_board *board, EXPORT_SYMBOL(nubus_get_root_dir); /* This is a slyly renamed version of the above */ -int nubus_get_func_dir(const struct nubus_dev *dev, - struct nubus_dir *dir) +int nubus_get_func_dir(const struct nubus_rsrc *fres, struct nubus_dir *dir) { - dir->ptr = dir->base = dev->directory; + dir->ptr = dir->base = fres->directory; dir->done = 0; - dir->mask = dev->board->lanes; + dir->mask = fres->board->lanes; return 0; } EXPORT_SYMBOL(nubus_get_func_dir); @@ -306,11 +305,10 @@ EXPORT_SYMBOL(nubus_rewinddir); /* Driver interface functions, more or less like in pci.c */ -struct nubus_dev* -nubus_find_type(unsigned short category, unsigned short type, - const struct nubus_dev *from) +struct nubus_rsrc *nubus_find_type(unsigned short category, unsigned short type, + const struct nubus_rsrc *from) { - struct nubus_dev *itor = from ? from->next : nubus_devices; + struct nubus_rsrc *itor = from ? from->next : nubus_func_rsrcs; while (itor) { if (itor->category == category && itor->type == type) @@ -321,10 +319,10 @@ nubus_find_type(unsigned short category, unsigned short type, } EXPORT_SYMBOL(nubus_find_type); -struct nubus_dev* -nubus_find_slot(unsigned int slot, const struct nubus_dev *from) +struct nubus_rsrc *nubus_find_slot(unsigned int slot, + const struct nubus_rsrc *from) { - struct nubus_dev *itor = from ? from->next : nubus_devices; + struct nubus_rsrc *itor = from ? from->next : nubus_func_rsrcs; while (itor) { if (itor->board->slot == slot) @@ -403,19 +401,19 @@ static int __init nubus_get_display_vidmode(struct nubus_board *board, return 0; } -static int __init nubus_get_display_resource(struct nubus_dev *dev, +static int __init nubus_get_display_resource(struct nubus_rsrc *fres, struct proc_dir_entry *procdir, const struct nubus_dirent *ent) { switch (ent->type) { case NUBUS_RESID_GAMMADIR: pr_debug(" gamma directory offset: 0x%06x\n", ent->data); - nubus_get_block_rsrc_dir(dev->board, procdir, ent); + nubus_get_block_rsrc_dir(fres->board, procdir, ent); break; case 0x0080 ... 0x0085: pr_debug(" mode 0x%02x info offset: 0x%06x\n", ent->type, ent->data); - nubus_get_display_vidmode(dev->board, procdir, ent); + nubus_get_display_vidmode(fres->board, procdir, ent); break; default: pr_debug(" unknown resource 0x%02x, data 0x%06x\n", @@ -425,7 +423,7 @@ static int __init nubus_get_display_resource(struct nubus_dev *dev, return 0; } -static int __init nubus_get_network_resource(struct nubus_dev *dev, +static int __init nubus_get_network_resource(struct nubus_rsrc *fres, struct proc_dir_entry *procdir, const struct nubus_dirent *ent) { @@ -447,7 +445,7 @@ static int __init nubus_get_network_resource(struct nubus_dev *dev, return 0; } -static int __init nubus_get_cpu_resource(struct nubus_dev *dev, +static int __init nubus_get_cpu_resource(struct nubus_rsrc *fres, struct proc_dir_entry *procdir, const struct nubus_dirent *ent) { @@ -480,19 +478,19 @@ static int __init nubus_get_cpu_resource(struct nubus_dev *dev, return 0; } -static int __init nubus_get_private_resource(struct nubus_dev *dev, +static int __init nubus_get_private_resource(struct nubus_rsrc *fres, struct proc_dir_entry *procdir, const struct nubus_dirent *ent) { - switch (dev->category) { + switch (fres->category) { case NUBUS_CAT_DISPLAY: - nubus_get_display_resource(dev, procdir, ent); + nubus_get_display_resource(fres, procdir, ent); break; case NUBUS_CAT_NETWORK: - nubus_get_network_resource(dev, procdir, ent); + nubus_get_network_resource(fres, procdir, ent); break; case NUBUS_CAT_CPU: - nubus_get_cpu_resource(dev, procdir, ent); + nubus_get_cpu_resource(fres, procdir, ent); break; default: pr_debug(" unknown resource 0x%02x, data 0x%06x\n", @@ -502,24 +500,25 @@ static int __init nubus_get_private_resource(struct nubus_dev *dev, return 0; } -static struct nubus_dev * __init +static struct nubus_rsrc * __init nubus_get_functional_resource(struct nubus_board *board, int slot, const struct nubus_dirent *parent) { struct nubus_dir dir; struct nubus_dirent ent; - struct nubus_dev *dev; + struct nubus_rsrc *fres; pr_debug(" Functional resource 0x%02x:\n", parent->type); nubus_get_subdir(parent, &dir); dir.procdir = nubus_proc_add_rsrc_dir(board->procdir, parent, board); /* Actually we should probably panic if this fails */ - if ((dev = kzalloc(sizeof(*dev), GFP_ATOMIC)) == NULL) + fres = kzalloc(sizeof(*fres), GFP_ATOMIC); + if (!fres) return NULL; - dev->resid = parent->type; - dev->directory = dir.base; - dev->board = board; + fres->resid = parent->type; + fres->directory = dir.base; + fres->board = board; while (nubus_readdir(&dir, &ent) != -1) { switch (ent.type) { @@ -528,10 +527,10 @@ nubus_get_functional_resource(struct nubus_board *board, int slot, unsigned short nbtdata[4]; nubus_get_rsrc_mem(nbtdata, &ent, 8); - dev->category = nbtdata[0]; - dev->type = nbtdata[1]; - dev->dr_sw = nbtdata[2]; - dev->dr_hw = nbtdata[3]; + fres->category = nbtdata[0]; + fres->type = nbtdata[1]; + fres->dr_sw = nbtdata[2]; + fres->dr_hw = nbtdata[3]; pr_debug(" type: [cat 0x%x type 0x%x sw 0x%x hw 0x%x]\n", nbtdata[0], nbtdata[1], nbtdata[2], nbtdata[3]); nubus_proc_add_rsrc_mem(dir.procdir, &ent, 8); @@ -589,11 +588,11 @@ nubus_get_functional_resource(struct nubus_board *board, int slot, default: /* Local/Private resources have their own function */ - nubus_get_private_resource(dev, dir.procdir, &ent); + nubus_get_private_resource(fres, dir.procdir, &ent); } } - return dev; + return fres; } /* This is *really* cool. */ @@ -729,7 +728,6 @@ static int __init nubus_get_board_resource(struct nubus_board *board, int slot, return 0; } -/* Add a board (might be many devices) to the list */ static struct nubus_board * __init nubus_add_board(int slot, int bytelanes) { struct nubus_board *board; @@ -801,10 +799,11 @@ static struct nubus_board * __init nubus_add_board(int slot, int bytelanes) pr_debug("Slot %X resources:\n", slot); /* Each slot should have one board resource and any number of - functional resources. So we'll fill in some fields in the - struct nubus_board from the board resource, then walk down - the list of functional resources, spinning out a nubus_dev - for each of them. */ + * functional resources. So we'll fill in some fields in the + * struct nubus_board from the board resource, then walk down + * the list of functional resources, spinning out a nubus_rsrc + * for each of them. + */ if (nubus_readdir(&dir, &ent) == -1) { /* We can't have this! */ pr_err("Slot %X: Board resource not found!\n", slot); @@ -819,32 +818,32 @@ static struct nubus_board * __init nubus_add_board(int slot, int bytelanes) nubus_get_board_resource(board, slot, &ent); while (nubus_readdir(&dir, &ent) != -1) { - struct nubus_dev *dev; - struct nubus_dev **devp; + struct nubus_rsrc *fres; + struct nubus_rsrc **fresp; - dev = nubus_get_functional_resource(board, slot, &ent); - if (dev == NULL) + fres = nubus_get_functional_resource(board, slot, &ent); + if (fres == NULL) continue; /* Resources should appear in ascending ID order. This sanity * check prevents duplicate resource IDs. */ - if (dev->resid <= prev_resid) { - kfree(dev); + if (fres->resid <= prev_resid) { + kfree(fres); continue; } - prev_resid = dev->resid; + prev_resid = fres->resid; /* We zeroed this out above */ - if (board->first_dev == NULL) - board->first_dev = dev; + if (board->first_func_rsrc == NULL) + board->first_func_rsrc = fres; - /* Put it on the global NuBus device chain. Keep entries in order. */ - for (devp = &nubus_devices; *devp != NULL; - devp = &((*devp)->next)) + /* Put it on the func. resource list. Keep entries in order. */ + for (fresp = &nubus_func_rsrcs; *fresp != NULL; + fresp = &((*fresp)->next)) /* spin */; - *devp = dev; - dev->next = NULL; + *fresp = fres; + fres->next = NULL; } /* Put it on the global NuBus board chain. Keep entries in order. */ diff --git a/drivers/nubus/proc.c b/drivers/nubus/proc.c index f47d90924ab4..f2b118330be0 100644 --- a/drivers/nubus/proc.c +++ b/drivers/nubus/proc.c @@ -36,17 +36,14 @@ static int nubus_devices_proc_show(struct seq_file *m, void *v) { - struct nubus_dev *dev = nubus_devices; + struct nubus_rsrc *fres = nubus_func_rsrcs; - while (dev) { + while (fres) { seq_printf(m, "%x\t%04x %04x %04x %04x", - dev->board->slot, - dev->category, - dev->type, - dev->dr_sw, - dev->dr_hw); - seq_printf(m, "\t%08lx\n", dev->board->slot_addr); - dev = dev->next; + fres->board->slot, fres->category, fres->type, + fres->dr_sw, fres->dr_hw); + seq_printf(m, "\t%08lx\n", fres->board->slot_addr); + fres = fres->next; } return 0; } diff --git a/drivers/video/fbdev/macfb.c b/drivers/video/fbdev/macfb.c index cda7587cbc86..e86a2796e3d9 100644 --- a/drivers/video/fbdev/macfb.c +++ b/drivers/video/fbdev/macfb.c @@ -556,7 +556,7 @@ static void __init iounmap_macfb(void) static int __init macfb_init(void) { int video_cmap_len, video_is_nubus = 0; - struct nubus_dev* ndev = NULL; + struct nubus_rsrc *ndev = NULL; char *option = NULL; int err; diff --git a/include/linux/nubus.h b/include/linux/nubus.h index 0a9e08e76606..4a481610ad38 100644 --- a/include/linux/nubus.h +++ b/include/linux/nubus.h @@ -33,7 +33,7 @@ struct nubus_dirent { struct nubus_board { struct nubus_board *next; - struct nubus_dev *first_dev; + struct nubus_rsrc *first_func_rsrc; /* Only 9-E actually exist, though 0-8 are also theoretically possible, and 0 is a special case which represents the @@ -62,11 +62,11 @@ struct nubus_board { struct proc_dir_entry *procdir; }; -struct nubus_dev { - /* Next link in device list */ - struct nubus_dev *next; +struct nubus_rsrc { + /* Next link in list */ + struct nubus_rsrc *next; - /* The functional resource ID of this device */ + /* The functional resource ID */ unsigned char resid; /* These are mostly here for convenience; we could always read them from the ROMs if we wanted to */ @@ -81,8 +81,8 @@ struct nubus_dev { struct nubus_board *board; }; -/* This is all NuBus devices (used to find devices later on) */ -extern struct nubus_dev *nubus_devices; +/* This is all NuBus functional resources (used to find devices later on) */ +extern struct nubus_rsrc *nubus_func_rsrcs; /* This is all NuBus cards */ extern struct nubus_board *nubus_boards; @@ -115,13 +115,12 @@ static inline void nubus_proc_add_rsrc(struct proc_dir_entry *procdir, const struct nubus_dirent *ent) {} #endif -/* If we need more precision we can add some more of these */ -struct nubus_dev *nubus_find_type(unsigned short category, - unsigned short type, - const struct nubus_dev *from); -/* Might have more than one device in a slot, you know... */ -struct nubus_dev *nubus_find_slot(unsigned int slot, - const struct nubus_dev *from); +struct nubus_rsrc *nubus_find_type(unsigned short category, + unsigned short type, + const struct nubus_rsrc *from); + +struct nubus_rsrc *nubus_find_slot(unsigned int slot, + const struct nubus_rsrc *from); /* These are somewhat more NuBus-specific. They all return 0 for success and -1 for failure, as you'd expect. */ @@ -134,8 +133,7 @@ int nubus_get_root_dir(const struct nubus_board *board, int nubus_get_board_dir(const struct nubus_board *board, struct nubus_dir *dir); /* The functional directory */ -int nubus_get_func_dir(const struct nubus_dev *dev, - struct nubus_dir *dir); +int nubus_get_func_dir(const struct nubus_rsrc *fres, struct nubus_dir *dir); /* These work on any directory gotten via the above */ int nubus_readdir(struct nubus_dir *dir, From 41b848160eabb22957652936b66ccafd95ab5ad8 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sat, 13 Jan 2018 17:37:13 -0500 Subject: [PATCH 13/17] nubus: Adopt standard linked list implementation This increases code re-use and improves readability. Cc: "David S. Miller" Cc: Bartlomiej Zolnierkiewicz Acked-by: Bartlomiej Zolnierkiewicz Tested-by: Stan Johnson Signed-off-by: Finn Thain Signed-off-by: Geert Uytterhoeven --- drivers/net/ethernet/8390/mac8390.c | 7 ++-- drivers/net/ethernet/cirrus/mac89x0.c | 6 ++-- drivers/net/ethernet/natsemi/macsonic.c | 8 +++-- drivers/nubus/nubus.c | 45 ++++++------------------- drivers/nubus/proc.c | 11 +++--- drivers/video/fbdev/macfb.c | 8 +++-- include/linux/nubus.h | 15 ++++----- 7 files changed, 40 insertions(+), 60 deletions(-) diff --git a/drivers/net/ethernet/8390/mac8390.c b/drivers/net/ethernet/8390/mac8390.c index 929ff6419621..2f91ce8dc614 100644 --- a/drivers/net/ethernet/8390/mac8390.c +++ b/drivers/net/ethernet/8390/mac8390.c @@ -416,8 +416,11 @@ struct net_device * __init mac8390_probe(int unit) if (unit >= 0) sprintf(dev->name, "eth%d", unit); - while ((ndev = nubus_find_type(NUBUS_CAT_NETWORK, NUBUS_TYPE_ETHERNET, - ndev))) { + for_each_func_rsrc(ndev) { + if (ndev->category != NUBUS_CAT_NETWORK || + ndev->type != NUBUS_TYPE_ETHERNET) + continue; + /* Have we seen it already? */ if (slots & (1 << ndev->board->slot)) continue; diff --git a/drivers/net/ethernet/cirrus/mac89x0.c b/drivers/net/ethernet/cirrus/mac89x0.c index f910f0f386d6..977d4c2c759d 100644 --- a/drivers/net/ethernet/cirrus/mac89x0.c +++ b/drivers/net/ethernet/cirrus/mac89x0.c @@ -187,6 +187,7 @@ struct net_device * __init mac89x0_probe(int unit) unsigned long ioaddr; unsigned short sig; int err = -ENODEV; + struct nubus_rsrc *fres; if (!MACH_IS_MAC) return ERR_PTR(-ENODEV); @@ -207,8 +208,9 @@ struct net_device * __init mac89x0_probe(int unit) /* We might have to parameterize this later */ slot = 0xE; /* Get out now if there's a real NuBus card in slot E */ - if (nubus_find_slot(slot, NULL) != NULL) - goto out; + for_each_func_rsrc(fres) + if (fres->board->slot == slot) + goto out; /* The pseudo-ISA bits always live at offset 0x300 (gee, wonder why...) */ diff --git a/drivers/net/ethernet/natsemi/macsonic.c b/drivers/net/ethernet/natsemi/macsonic.c index 14f3fb50dc21..313fe5e0184b 100644 --- a/drivers/net/ethernet/natsemi/macsonic.c +++ b/drivers/net/ethernet/natsemi/macsonic.c @@ -464,9 +464,11 @@ static int mac_nubus_sonic_probe(struct net_device *dev) int reg_offset, dma_bitmode; /* Find the first SONIC that hasn't been initialized already */ - while ((ndev = nubus_find_type(NUBUS_CAT_NETWORK, - NUBUS_TYPE_ETHERNET, ndev)) != NULL) - { + for_each_func_rsrc(ndev) { + if (ndev->category != NUBUS_CAT_NETWORK || + ndev->type != NUBUS_TYPE_ETHERNET) + continue; + /* Have we seen it already? */ if (slots & (1<board->slot)) continue; diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c index 3657b13c0022..0bb54ccd7a1a 100644 --- a/drivers/nubus/nubus.c +++ b/drivers/nubus/nubus.c @@ -32,7 +32,7 @@ /* Globals */ -struct nubus_rsrc *nubus_func_rsrcs; +LIST_HEAD(nubus_func_rsrcs); struct nubus_board *nubus_boards; /* Meaning of "bytelanes": @@ -305,33 +305,20 @@ EXPORT_SYMBOL(nubus_rewinddir); /* Driver interface functions, more or less like in pci.c */ -struct nubus_rsrc *nubus_find_type(unsigned short category, unsigned short type, - const struct nubus_rsrc *from) +struct nubus_rsrc *nubus_first_rsrc_or_null(void) { - struct nubus_rsrc *itor = from ? from->next : nubus_func_rsrcs; - - while (itor) { - if (itor->category == category && itor->type == type) - return itor; - itor = itor->next; - } - return NULL; + return list_first_entry_or_null(&nubus_func_rsrcs, struct nubus_rsrc, + list); } -EXPORT_SYMBOL(nubus_find_type); +EXPORT_SYMBOL(nubus_first_rsrc_or_null); -struct nubus_rsrc *nubus_find_slot(unsigned int slot, - const struct nubus_rsrc *from) +struct nubus_rsrc *nubus_next_rsrc_or_null(struct nubus_rsrc *from) { - struct nubus_rsrc *itor = from ? from->next : nubus_func_rsrcs; - - while (itor) { - if (itor->board->slot == slot) - return itor; - itor = itor->next; - } - return NULL; + if (list_is_last(&from->list, &nubus_func_rsrcs)) + return NULL; + return list_next_entry(from, list); } -EXPORT_SYMBOL(nubus_find_slot); +EXPORT_SYMBOL(nubus_next_rsrc_or_null); int nubus_find_rsrc(struct nubus_dir *dir, unsigned char rsrc_type, @@ -819,7 +806,6 @@ static struct nubus_board * __init nubus_add_board(int slot, int bytelanes) while (nubus_readdir(&dir, &ent) != -1) { struct nubus_rsrc *fres; - struct nubus_rsrc **fresp; fres = nubus_get_functional_resource(board, slot, &ent); if (fres == NULL) @@ -834,16 +820,7 @@ static struct nubus_board * __init nubus_add_board(int slot, int bytelanes) } prev_resid = fres->resid; - /* We zeroed this out above */ - if (board->first_func_rsrc == NULL) - board->first_func_rsrc = fres; - - /* Put it on the func. resource list. Keep entries in order. */ - for (fresp = &nubus_func_rsrcs; *fresp != NULL; - fresp = &((*fresp)->next)) - /* spin */; - *fresp = fres; - fres->next = NULL; + list_add_tail(&fres->list, &nubus_func_rsrcs); } /* Put it on the global NuBus board chain. Keep entries in order. */ diff --git a/drivers/nubus/proc.c b/drivers/nubus/proc.c index f2b118330be0..60c0f40b4d5e 100644 --- a/drivers/nubus/proc.c +++ b/drivers/nubus/proc.c @@ -36,15 +36,12 @@ static int nubus_devices_proc_show(struct seq_file *m, void *v) { - struct nubus_rsrc *fres = nubus_func_rsrcs; + struct nubus_rsrc *fres; - while (fres) { - seq_printf(m, "%x\t%04x %04x %04x %04x", + for_each_func_rsrc(fres) + seq_printf(m, "%x\t%04x %04x %04x %04x\t%08lx\n", fres->board->slot, fres->category, fres->type, - fres->dr_sw, fres->dr_hw); - seq_printf(m, "\t%08lx\n", fres->board->slot_addr); - fres = fres->next; - } + fres->dr_sw, fres->dr_hw, fres->board->slot_addr); return 0; } diff --git a/drivers/video/fbdev/macfb.c b/drivers/video/fbdev/macfb.c index e86a2796e3d9..e707e617bf1c 100644 --- a/drivers/video/fbdev/macfb.c +++ b/drivers/video/fbdev/macfb.c @@ -670,15 +670,17 @@ static int __init macfb_init(void) * code is really broken :-) */ - while ((ndev = nubus_find_type(NUBUS_CAT_DISPLAY, - NUBUS_TYPE_VIDEO, ndev))) - { + for_each_func_rsrc(ndev) { unsigned long base = ndev->board->slot_addr; if (mac_bi_data.videoaddr < base || mac_bi_data.videoaddr - base > 0xFFFFFF) continue; + if (ndev->category != NUBUS_CAT_DISPLAY || + ndev->type != NUBUS_TYPE_VIDEO) + continue; + video_is_nubus = 1; slot_addr = (unsigned char *)base; diff --git a/include/linux/nubus.h b/include/linux/nubus.h index 4a481610ad38..2cbc7a199bca 100644 --- a/include/linux/nubus.h +++ b/include/linux/nubus.h @@ -33,7 +33,6 @@ struct nubus_dirent { struct nubus_board { struct nubus_board *next; - struct nubus_rsrc *first_func_rsrc; /* Only 9-E actually exist, though 0-8 are also theoretically possible, and 0 is a special case which represents the @@ -63,8 +62,7 @@ struct nubus_board { }; struct nubus_rsrc { - /* Next link in list */ - struct nubus_rsrc *next; + struct list_head list; /* The functional resource ID */ unsigned char resid; @@ -82,7 +80,7 @@ struct nubus_rsrc { }; /* This is all NuBus functional resources (used to find devices later on) */ -extern struct nubus_rsrc *nubus_func_rsrcs; +extern struct list_head nubus_func_rsrcs; /* This is all NuBus cards */ extern struct nubus_board *nubus_boards; @@ -115,12 +113,11 @@ static inline void nubus_proc_add_rsrc(struct proc_dir_entry *procdir, const struct nubus_dirent *ent) {} #endif -struct nubus_rsrc *nubus_find_type(unsigned short category, - unsigned short type, - const struct nubus_rsrc *from); +struct nubus_rsrc *nubus_first_rsrc_or_null(void); +struct nubus_rsrc *nubus_next_rsrc_or_null(struct nubus_rsrc *from); -struct nubus_rsrc *nubus_find_slot(unsigned int slot, - const struct nubus_rsrc *from); +#define for_each_func_rsrc(f) \ + for (f = nubus_first_rsrc_or_null(); f; f = nubus_next_rsrc_or_null(f)) /* These are somewhat more NuBus-specific. They all return 0 for success and -1 for failure, as you'd expect. */ From b87eaec27eca3def6c8ed617e3b1bac08d7bc715 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sat, 13 Jan 2018 17:37:13 -0500 Subject: [PATCH 14/17] nubus: Add expansion_type values for various Mac models Add an expansion slot attribute to allow drivers to properly handle cards like Comm Slot cards and PDS cards without declaration ROMs. This clarifies the logic for the Centris 610 model which has no Comm Slot but has an optional on-board SONIC device. Cc: "David S. Miller" Tested-by: Stan Johnson Signed-off-by: Finn Thain Signed-off-by: Geert Uytterhoeven --- arch/m68k/include/asm/macintosh.h | 9 +- arch/m68k/mac/config.c | 110 ++++++++++-------------- drivers/net/ethernet/natsemi/macsonic.c | 8 +- 3 files changed, 54 insertions(+), 73 deletions(-) diff --git a/arch/m68k/include/asm/macintosh.h b/arch/m68k/include/asm/macintosh.h index f42c27400dbc..9b840c03ebb7 100644 --- a/arch/m68k/include/asm/macintosh.h +++ b/arch/m68k/include/asm/macintosh.h @@ -33,7 +33,7 @@ struct mac_model char ide_type; char scc_type; char ether_type; - char nubus_type; + char expansion_type; char floppy_type; }; @@ -73,8 +73,11 @@ struct mac_model #define MAC_ETHER_SONIC 1 #define MAC_ETHER_MACE 2 -#define MAC_NO_NUBUS 0 -#define MAC_NUBUS 1 +#define MAC_EXP_NONE 0 +#define MAC_EXP_PDS 1 /* Accepts only a PDS card */ +#define MAC_EXP_NUBUS 2 /* Accepts only NuBus card(s) */ +#define MAC_EXP_PDS_NUBUS 3 /* Accepts PDS card and/or NuBus card(s) */ +#define MAC_EXP_PDS_COMM 4 /* Accepts PDS card or Comm Slot card */ #define MAC_FLOPPY_IWM 0 #define MAC_FLOPPY_SWIM_ADDR1 1 diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c index 16cd5cea5207..d3d435248a24 100644 --- a/arch/m68k/mac/config.c +++ b/arch/m68k/mac/config.c @@ -212,7 +212,7 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_II, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_NUBUS, .floppy_type = MAC_FLOPPY_IWM, }, @@ -227,7 +227,7 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_II, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_NUBUS, .floppy_type = MAC_FLOPPY_IWM, }, { .ident = MAC_MODEL_IIX, @@ -236,7 +236,7 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_II, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_IICX, @@ -245,7 +245,7 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_II, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_SE30, @@ -254,7 +254,7 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_II, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_PDS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, @@ -272,7 +272,7 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_IIFX, @@ -281,7 +281,7 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_IIFX, .scc_type = MAC_SCC_IOP, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_PDS_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_IOP, }, { .ident = MAC_MODEL_IISI, @@ -290,7 +290,7 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_PDS_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_IIVI, @@ -299,7 +299,7 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_LC, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_IIVX, @@ -308,7 +308,7 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_LC, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, @@ -323,7 +323,6 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_LC, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_CCL, @@ -332,7 +331,7 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_LC, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_PDS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_CCLII, @@ -341,7 +340,7 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_LC, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_PDS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, @@ -356,7 +355,7 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_LC, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_PDS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_LCII, @@ -365,7 +364,7 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_LC, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_PDS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_LCIII, @@ -374,7 +373,7 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_LC, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_PDS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, @@ -395,7 +394,7 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_QUADRA, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_PDS, .floppy_type = MAC_FLOPPY_SWIM_ADDR1, }, { .ident = MAC_MODEL_Q605_ACC, @@ -404,7 +403,7 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_QUADRA, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_PDS, .floppy_type = MAC_FLOPPY_SWIM_ADDR1, }, { .ident = MAC_MODEL_Q610, @@ -414,7 +413,7 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA, .scc_type = MAC_SCC_QUADRA, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_PDS_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR1, }, { .ident = MAC_MODEL_Q630, @@ -424,8 +423,7 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA, .ide_type = MAC_IDE_QUADRA, .scc_type = MAC_SCC_QUADRA, - .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_PDS_COMM, .floppy_type = MAC_FLOPPY_SWIM_ADDR1, }, { .ident = MAC_MODEL_Q650, @@ -435,7 +433,7 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA, .scc_type = MAC_SCC_QUADRA, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_PDS_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR1, }, /* The Q700 does have a NS Sonic */ @@ -447,7 +445,7 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA2, .scc_type = MAC_SCC_QUADRA, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_PDS_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR1, }, { .ident = MAC_MODEL_Q800, @@ -457,7 +455,7 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA, .scc_type = MAC_SCC_QUADRA, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_PDS_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR1, }, { .ident = MAC_MODEL_Q840, @@ -467,7 +465,7 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA3, .scc_type = MAC_SCC_PSC, .ether_type = MAC_ETHER_MACE, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_NUBUS, .floppy_type = MAC_FLOPPY_AV, }, { .ident = MAC_MODEL_Q900, @@ -477,7 +475,7 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA2, .scc_type = MAC_SCC_IOP, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_PDS_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_IOP, }, { .ident = MAC_MODEL_Q950, @@ -487,7 +485,7 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA2, .scc_type = MAC_SCC_IOP, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_PDS_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_IOP, }, @@ -502,7 +500,7 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_LC, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_PDS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_P475, @@ -511,7 +509,7 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_QUADRA, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_PDS, .floppy_type = MAC_FLOPPY_SWIM_ADDR1, }, { .ident = MAC_MODEL_P475F, @@ -520,7 +518,7 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_QUADRA, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_PDS, .floppy_type = MAC_FLOPPY_SWIM_ADDR1, }, { .ident = MAC_MODEL_P520, @@ -529,7 +527,7 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_LC, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_PDS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_P550, @@ -538,7 +536,7 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_LC, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_PDS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, /* These have the comm slot, and therefore possibly SONIC ethernet */ @@ -549,8 +547,7 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_QUADRA, .scc_type = MAC_SCC_II, - .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_PDS_COMM, .floppy_type = MAC_FLOPPY_SWIM_ADDR1, }, { .ident = MAC_MODEL_P588, @@ -560,8 +557,7 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA, .ide_type = MAC_IDE_QUADRA, .scc_type = MAC_SCC_II, - .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_PDS_COMM, .floppy_type = MAC_FLOPPY_SWIM_ADDR1, }, { .ident = MAC_MODEL_TV, @@ -570,7 +566,6 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_LC, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_P600, @@ -579,7 +574,7 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_LC, .scc_type = MAC_SCC_II, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, @@ -596,7 +591,7 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA, .scc_type = MAC_SCC_QUADRA, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_PDS_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR1, }, { .ident = MAC_MODEL_C650, @@ -606,7 +601,7 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA, .scc_type = MAC_SCC_QUADRA, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_PDS_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR1, }, { .ident = MAC_MODEL_C660, @@ -616,7 +611,7 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_QUADRA3, .scc_type = MAC_SCC_PSC, .ether_type = MAC_ETHER_MACE, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_PDS_NUBUS, .floppy_type = MAC_FLOPPY_AV, }, @@ -633,7 +628,6 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_PB145, @@ -642,7 +636,6 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_PB150, @@ -652,7 +645,6 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_OLD, .ide_type = MAC_IDE_PB, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_PB160, @@ -661,7 +653,6 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_PB165, @@ -670,7 +661,6 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_PB165C, @@ -679,7 +669,6 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_PB170, @@ -688,7 +677,6 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_PB180, @@ -697,7 +685,6 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_PB180C, @@ -706,7 +693,6 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_QUADRA, .scsi_type = MAC_SCSI_OLD, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_PB190, @@ -716,7 +702,6 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_LATE, .ide_type = MAC_IDE_BABOON, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_PB520, @@ -726,7 +711,6 @@ static struct mac_model mac_data_table[] = { .scsi_type = MAC_SCSI_LATE, .scc_type = MAC_SCC_QUADRA, .ether_type = MAC_ETHER_SONIC, - .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, @@ -743,7 +727,7 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_DUO, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_PB230, @@ -752,7 +736,7 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_DUO, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_PB250, @@ -761,7 +745,7 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_DUO, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_PB270C, @@ -770,7 +754,7 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_DUO, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_PB280, @@ -779,7 +763,7 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_DUO, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, { .ident = MAC_MODEL_PB280C, @@ -788,7 +772,7 @@ static struct mac_model mac_data_table[] = { .via_type = MAC_VIA_IICI, .scsi_type = MAC_SCSI_DUO, .scc_type = MAC_SCC_QUADRA, - .nubus_type = MAC_NUBUS, + .expansion_type = MAC_EXP_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, }, @@ -1100,14 +1084,12 @@ int __init mac_platform_init(void) * Ethernet device */ - switch (macintosh_config->ether_type) { - case MAC_ETHER_SONIC: + if (macintosh_config->ether_type == MAC_ETHER_SONIC || + macintosh_config->expansion_type == MAC_EXP_PDS_COMM) platform_device_register_simple("macsonic", -1, NULL, 0); - break; - case MAC_ETHER_MACE: + + if (macintosh_config->ether_type == MAC_ETHER_MACE) platform_device_register_simple("macmace", -1, NULL, 0); - break; - } return 0; } diff --git a/drivers/net/ethernet/natsemi/macsonic.c b/drivers/net/ethernet/natsemi/macsonic.c index 313fe5e0184b..b922ab5cedea 100644 --- a/drivers/net/ethernet/natsemi/macsonic.c +++ b/drivers/net/ethernet/natsemi/macsonic.c @@ -311,7 +311,7 @@ static int mac_onboard_sonic_probe(struct net_device *dev) { struct sonic_local* lp = netdev_priv(dev); int sr; - int commslot = 0; + bool commslot = macintosh_config->expansion_type == MAC_EXP_PDS_COMM; if (!MACH_IS_MAC) return -ENODEV; @@ -322,10 +322,7 @@ static int mac_onboard_sonic_probe(struct net_device *dev) Ethernet (BTW, the Ethernet *is* always at the same address, and nothing else lives there, at least if Apple's documentation is to be believed) */ - if (macintosh_config->ident == MAC_MODEL_Q630 || - macintosh_config->ident == MAC_MODEL_P588 || - macintosh_config->ident == MAC_MODEL_P575 || - macintosh_config->ident == MAC_MODEL_C610) { + if (commslot || macintosh_config->ident == MAC_MODEL_C610) { int card_present; card_present = hwreg_present((void*)ONBOARD_SONIC_REGISTERS); @@ -333,7 +330,6 @@ static int mac_onboard_sonic_probe(struct net_device *dev) printk("none.\n"); return -ENODEV; } - commslot = 1; } printk("yes\n"); From 7f86c765a6a2bb837c45f11526176125ff50e21f Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sat, 13 Jan 2018 17:37:14 -0500 Subject: [PATCH 15/17] nubus: Add support for the driver model This patch brings basic support for the Linux Driver Model to the NuBus subsystem. For flexibility, the matching of boards with drivers is left up to the drivers. This is also the approach taken by NetBSD. A board may have many functions, and drivers may have to consider many functional resources and board resources in order to match a device. This implementation does not bind drivers to resources (nor does it bind many drivers to the same board). Apple's NuBus declaration ROM design is flexible enough to allow that, but I don't see a need to support it as we don't use the "slot zero" resources (in the main logic board ROM). Eliminate the global nubus_boards linked list by rewriting the procfs board iterator around bus_for_each_dev(). Hence the nubus device refcount can be used to determine the lifespan of board objects. Cc: Greg Kroah-Hartman Reviewed-by: Greg Kroah-Hartman Tested-by: Stan Johnson Signed-off-by: Finn Thain Signed-off-by: Geert Uytterhoeven --- drivers/nubus/Makefile | 2 +- drivers/nubus/bus.c | 117 +++++++++++++++++++++++++++++++++++++++++ drivers/nubus/nubus.c | 24 ++++----- drivers/nubus/proc.c | 55 +------------------ include/linux/nubus.h | 33 ++++++++++-- 5 files changed, 161 insertions(+), 70 deletions(-) create mode 100644 drivers/nubus/bus.c diff --git a/drivers/nubus/Makefile b/drivers/nubus/Makefile index 21bda2031e7e..6d063cde39d1 100644 --- a/drivers/nubus/Makefile +++ b/drivers/nubus/Makefile @@ -2,6 +2,6 @@ # Makefile for the nubus specific drivers. # -obj-y := nubus.o +obj-y := nubus.o bus.o obj-$(CONFIG_PROC_FS) += proc.o diff --git a/drivers/nubus/bus.c b/drivers/nubus/bus.c new file mode 100644 index 000000000000..d306c348c857 --- /dev/null +++ b/drivers/nubus/bus.c @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Bus implementation for the NuBus subsystem. +// +// Copyright (C) 2017 Finn Thain + +#include +#include +#include +#include +#include + +#define to_nubus_board(d) container_of(d, struct nubus_board, dev) +#define to_nubus_driver(d) container_of(d, struct nubus_driver, driver) + +static int nubus_bus_match(struct device *dev, struct device_driver *driver) +{ + return 1; +} + +static int nubus_device_probe(struct device *dev) +{ + struct nubus_driver *ndrv = to_nubus_driver(dev->driver); + int err = -ENODEV; + + if (ndrv->probe) + err = ndrv->probe(to_nubus_board(dev)); + return err; +} + +static int nubus_device_remove(struct device *dev) +{ + struct nubus_driver *ndrv = to_nubus_driver(dev->driver); + int err = -ENODEV; + + if (dev->driver && ndrv->remove) + err = ndrv->remove(to_nubus_board(dev)); + return err; +} + +struct bus_type nubus_bus_type = { + .name = "nubus", + .match = nubus_bus_match, + .probe = nubus_device_probe, + .remove = nubus_device_remove, +}; +EXPORT_SYMBOL(nubus_bus_type); + +int nubus_driver_register(struct nubus_driver *ndrv) +{ + ndrv->driver.bus = &nubus_bus_type; + return driver_register(&ndrv->driver); +} +EXPORT_SYMBOL(nubus_driver_register); + +void nubus_driver_unregister(struct nubus_driver *ndrv) +{ + driver_unregister(&ndrv->driver); +} +EXPORT_SYMBOL(nubus_driver_unregister); + +static struct device nubus_parent = { + .init_name = "nubus", +}; + +int __init nubus_bus_register(void) +{ + int err; + + err = device_register(&nubus_parent); + if (err) + return err; + + err = bus_register(&nubus_bus_type); + if (!err) + return 0; + + device_unregister(&nubus_parent); + return err; +} + +static void nubus_device_release(struct device *dev) +{ + struct nubus_board *board = to_nubus_board(dev); + struct nubus_rsrc *fres, *tmp; + + list_for_each_entry_safe(fres, tmp, &nubus_func_rsrcs, list) + if (fres->board == board) { + list_del(&fres->list); + kfree(fres); + } + kfree(board); +} + +int nubus_device_register(struct nubus_board *board) +{ + board->dev.parent = &nubus_parent; + board->dev.release = nubus_device_release; + board->dev.bus = &nubus_bus_type; + dev_set_name(&board->dev, "slot.%X", board->slot); + return device_register(&board->dev); +} + +static int nubus_print_device_name_fn(struct device *dev, void *data) +{ + struct nubus_board *board = to_nubus_board(dev); + struct seq_file *m = data; + + seq_printf(m, "Slot %X: %s\n", board->slot, board->name); + return 0; +} + +int nubus_proc_show(struct seq_file *m, void *data) +{ + return bus_for_each_dev(&nubus_bus_type, NULL, m, + nubus_print_device_name_fn); +} diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c index 0bb54ccd7a1a..4621ff98138c 100644 --- a/drivers/nubus/nubus.c +++ b/drivers/nubus/nubus.c @@ -33,7 +33,6 @@ /* Globals */ LIST_HEAD(nubus_func_rsrcs); -struct nubus_board *nubus_boards; /* Meaning of "bytelanes": @@ -715,10 +714,9 @@ static int __init nubus_get_board_resource(struct nubus_board *board, int slot, return 0; } -static struct nubus_board * __init nubus_add_board(int slot, int bytelanes) +static void __init nubus_add_board(int slot, int bytelanes) { struct nubus_board *board; - struct nubus_board **boardp; unsigned char *rp; unsigned long dpat; struct nubus_dir dir; @@ -731,7 +729,7 @@ static struct nubus_board * __init nubus_add_board(int slot, int bytelanes) /* Actually we should probably panic if this fails */ if ((board = kzalloc(sizeof(*board), GFP_ATOMIC)) == NULL) - return NULL; + return; board->fblock = rp; /* Dump the format block for debugging purposes */ @@ -794,7 +792,8 @@ static struct nubus_board * __init nubus_add_board(int slot, int bytelanes) if (nubus_readdir(&dir, &ent) == -1) { /* We can't have this! */ pr_err("Slot %X: Board resource not found!\n", slot); - return NULL; + kfree(board); + return; } if (ent.type < 1 || ent.type > 127) @@ -823,14 +822,8 @@ static struct nubus_board * __init nubus_add_board(int slot, int bytelanes) list_add_tail(&fres->list, &nubus_func_rsrcs); } - /* Put it on the global NuBus board chain. Keep entries in order. */ - for (boardp = &nubus_boards; *boardp != NULL; - boardp = &((*boardp)->next)) - /* spin */; - *boardp = board; - board->next = NULL; - - return board; + if (nubus_device_register(board)) + put_device(&board->dev); } static void __init nubus_probe_slot(int slot) @@ -876,10 +869,15 @@ static void __init nubus_scan_bus(void) static int __init nubus_init(void) { + int err; + if (!MACH_IS_MAC) return 0; nubus_proc_init(); + err = nubus_bus_register(); + if (err) + return err; nubus_scan_bus(); return 0; } diff --git a/drivers/nubus/proc.c b/drivers/nubus/proc.c index 60c0f40b4d5e..c2e5a7e6bd3e 100644 --- a/drivers/nubus/proc.c +++ b/drivers/nubus/proc.c @@ -198,68 +198,17 @@ void nubus_proc_add_rsrc(struct proc_dir_entry *procdir, /* * /proc/nubus stuff */ -static int nubus_proc_show(struct seq_file *m, void *v) -{ - const struct nubus_board *board = v; - - /* Display header on line 1 */ - if (v == SEQ_START_TOKEN) - seq_puts(m, "Nubus devices found:\n"); - else - seq_printf(m, "Slot %X: %s\n", board->slot, board->name); - return 0; -} - -static void *nubus_proc_start(struct seq_file *m, loff_t *_pos) -{ - struct nubus_board *board; - unsigned pos; - - if (*_pos > LONG_MAX) - return NULL; - pos = *_pos; - if (pos == 0) - return SEQ_START_TOKEN; - for (board = nubus_boards; board; board = board->next) - if (--pos == 0) - break; - return board; -} - -static void *nubus_proc_next(struct seq_file *p, void *v, loff_t *_pos) -{ - /* Walk the list of NuBus boards */ - struct nubus_board *board = v; - - ++*_pos; - if (v == SEQ_START_TOKEN) - board = nubus_boards; - else if (board) - board = board->next; - return board; -} - -static void nubus_proc_stop(struct seq_file *p, void *v) -{ -} - -static const struct seq_operations nubus_proc_seqops = { - .start = nubus_proc_start, - .next = nubus_proc_next, - .stop = nubus_proc_stop, - .show = nubus_proc_show, -}; static int nubus_proc_open(struct inode *inode, struct file *file) { - return seq_open(file, &nubus_proc_seqops); + return single_open(file, nubus_proc_show, NULL); } static const struct file_operations nubus_proc_fops = { .open = nubus_proc_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release, + .release = single_release, }; void __init nubus_proc_init(void) diff --git a/include/linux/nubus.h b/include/linux/nubus.h index 2cbc7a199bca..6e8200215321 100644 --- a/include/linux/nubus.h +++ b/include/linux/nubus.h @@ -10,6 +10,7 @@ #ifndef LINUX_NUBUS_H #define LINUX_NUBUS_H +#include #include #include @@ -32,7 +33,7 @@ struct nubus_dirent { }; struct nubus_board { - struct nubus_board *next; + struct device dev; /* Only 9-E actually exist, though 0-8 are also theoretically possible, and 0 is a special case which represents the @@ -81,8 +82,14 @@ struct nubus_rsrc { /* This is all NuBus functional resources (used to find devices later on) */ extern struct list_head nubus_func_rsrcs; -/* This is all NuBus cards */ -extern struct nubus_board *nubus_boards; + +struct nubus_driver { + struct device_driver driver; + int (*probe)(struct nubus_board *board); + int (*remove)(struct nubus_board *board); +}; + +extern struct bus_type nubus_bus_type; /* Generic NuBus interface functions, modelled after the PCI interface */ #ifdef CONFIG_PROC_FS @@ -119,6 +126,9 @@ struct nubus_rsrc *nubus_next_rsrc_or_null(struct nubus_rsrc *from); #define for_each_func_rsrc(f) \ for (f = nubus_first_rsrc_or_null(); f; f = nubus_next_rsrc_or_null(f)) +#define for_each_board_func_rsrc(b, f) \ + for_each_func_rsrc(f) if (f->board != b) {} else + /* These are somewhat more NuBus-specific. They all return 0 for success and -1 for failure, as you'd expect. */ @@ -152,6 +162,23 @@ void nubus_seq_write_rsrc_mem(struct seq_file *m, unsigned int len); unsigned char *nubus_dirptr(const struct nubus_dirent *nd); +/* Declarations relating to driver model objects */ +int nubus_bus_register(void); +int nubus_device_register(struct nubus_board *board); +int nubus_driver_register(struct nubus_driver *ndrv); +void nubus_driver_unregister(struct nubus_driver *ndrv); +int nubus_proc_show(struct seq_file *m, void *data); + +static inline void nubus_set_drvdata(struct nubus_board *board, void *data) +{ + dev_set_drvdata(&board->dev, data); +} + +static inline void *nubus_get_drvdata(struct nubus_board *board) +{ + return dev_get_drvdata(&board->dev); +} + /* Returns a pointer to the "standard" slot space. */ static inline void *nubus_slot_addr(int slot) { From 317b749e37789ecb3366f304dab905a97e650b41 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sat, 13 Jan 2018 17:44:31 -0500 Subject: [PATCH 16/17] m68k/mac: Fix race conditions in OSS interrupt dispatch The interrupt dispatch algorithm used in the OSS driver seems to be subject to race conditions: an IRQ flag could be lost if asserted between the MOV instructions from and to the interrupt flag register. But testing shows that the write to the flag register has no effect, so rewrite the algorithm without the theoretical race condition. There is a second theoretical race condition here. When oss_irq() is called with say, IPL == 2 it will invoke the SCSI interrupt handler. The SCSI IRQ is then cleared by the mac_scsi driver. If SCSI and NuBus IRQs are now asserted together, oss_irq() will be invoked with IPL == 3 and the mac_scsi interrupt handler can be re-entered. This re-entrance issue is not limited to SCSI and could affect NuBus and ADB drivers too. Fix it by splitting up oss_irq() into separate handlers for each IPL. No-one seems to know how OSS irq flags can be cleared, if at all, so add a comment to this effect (actually reinstate one I previously removed). Testing showed that a slot IRQ with no handler can remain asserted (in this case a Radius video card) without causing problems for other IRQs. Tested-by: Stan Johnson Signed-off-by: Finn Thain Signed-off-by: Geert Uytterhoeven --- arch/m68k/mac/oss.c | 67 ++++++++++++++++++--------------------------- 1 file changed, 26 insertions(+), 41 deletions(-) diff --git a/arch/m68k/mac/oss.c b/arch/m68k/mac/oss.c index 3f81892527ad..921e6c092f2c 100644 --- a/arch/m68k/mac/oss.c +++ b/arch/m68k/mac/oss.c @@ -53,56 +53,41 @@ void __init oss_init(void) } /* - * Handle miscellaneous OSS interrupts. + * Handle OSS interrupts. + * XXX how do you clear a pending IRQ? is it even necessary? */ -static void oss_irq(struct irq_desc *desc) +static void oss_iopism_irq(struct irq_desc *desc) { - int events = oss->irq_pending & - (OSS_IP_IOPSCC | OSS_IP_SCSI | OSS_IP_IOPISM); - - if (events & OSS_IP_IOPSCC) { - oss->irq_pending &= ~OSS_IP_IOPSCC; - generic_handle_irq(IRQ_MAC_SCC); - } - - if (events & OSS_IP_SCSI) { - oss->irq_pending &= ~OSS_IP_SCSI; - generic_handle_irq(IRQ_MAC_SCSI); - } - - if (events & OSS_IP_IOPISM) { - oss->irq_pending &= ~OSS_IP_IOPISM; - generic_handle_irq(IRQ_MAC_ADB); - } + generic_handle_irq(IRQ_MAC_ADB); } -/* - * Nubus IRQ handler, OSS style - * - * Unlike the VIA/RBV this is on its own autovector interrupt level. - */ +static void oss_scsi_irq(struct irq_desc *desc) +{ + generic_handle_irq(IRQ_MAC_SCSI); +} static void oss_nubus_irq(struct irq_desc *desc) { - int events, irq_bit, i; + u16 events, irq_bit; + int irq_num; events = oss->irq_pending & OSS_IP_NUBUS; - if (!events) - return; - - /* There are only six slots on the OSS, not seven */ - - i = 6; - irq_bit = 0x40; + irq_num = NUBUS_SOURCE_BASE + 5; + irq_bit = OSS_IP_NUBUS5; do { - --i; - irq_bit >>= 1; if (events & irq_bit) { - oss->irq_pending &= ~irq_bit; - generic_handle_irq(NUBUS_SOURCE_BASE + i); + events &= ~irq_bit; + generic_handle_irq(irq_num); } - } while(events & (irq_bit - 1)); + --irq_num; + irq_bit >>= 1; + } while (events); +} + +static void oss_iopscc_irq(struct irq_desc *desc) +{ + generic_handle_irq(IRQ_MAC_SCC); } /* @@ -122,14 +107,14 @@ static void oss_nubus_irq(struct irq_desc *desc) void __init oss_register_interrupts(void) { - irq_set_chained_handler(OSS_IRQLEV_IOPISM, oss_irq); - irq_set_chained_handler(OSS_IRQLEV_SCSI, oss_irq); + irq_set_chained_handler(OSS_IRQLEV_IOPISM, oss_iopism_irq); + irq_set_chained_handler(OSS_IRQLEV_SCSI, oss_scsi_irq); irq_set_chained_handler(OSS_IRQLEV_NUBUS, oss_nubus_irq); - irq_set_chained_handler(OSS_IRQLEV_IOPSCC, oss_irq); + irq_set_chained_handler(OSS_IRQLEV_IOPSCC, oss_iopscc_irq); irq_set_chained_handler(OSS_IRQLEV_VIA1, via1_irq); /* OSS_VIA1 gets enabled here because it has no machspec interrupt. */ - oss->irq_level[OSS_VIA1] = IRQ_AUTO_6; + oss->irq_level[OSS_VIA1] = OSS_IRQLEV_VIA1; } /* From 2334b1ac1235934fc196f2d25bae7f348d3bf42e Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 14 Jan 2018 22:41:13 -0500 Subject: [PATCH 17/17] MAINTAINERS: Add NuBus subsystem entry This is legacy code but it might as well have an official maintainer. Cc: linux-m68k@lists.linux-m68k.org Signed-off-by: Finn Thain Signed-off-by: Geert Uytterhoeven --- MAINTAINERS | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index aa71ab52fd76..e572d6cbddbc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9745,6 +9745,15 @@ S: Supported F: Documentation/filesystems/ntfs.txt F: fs/ntfs/ +NUBUS SUBSYSTEM +M: Finn Thain +L: linux-m68k@lists.linux-m68k.org +S: Maintained +F: arch/*/include/asm/nubus.h +F: drivers/nubus/ +F: include/linux/nubus.h +F: include/uapi/linux/nubus.h + NVIDIA (rivafb and nvidiafb) FRAMEBUFFER DRIVER M: Antonino Daplas L: linux-fbdev@vger.kernel.org