diff options
Diffstat (limited to 'drivers/message/i2o')
| -rw-r--r-- | drivers/message/i2o/Kconfig | 31 | ||||
| -rw-r--r-- | drivers/message/i2o/Makefile | 2 | ||||
| -rw-r--r-- | drivers/message/i2o/README | 6 | ||||
| -rw-r--r-- | drivers/message/i2o/README.ioctl | 16 | ||||
| -rw-r--r-- | drivers/message/i2o/bus-osm.c | 38 | ||||
| -rw-r--r-- | drivers/message/i2o/config-osm.c | 2 | ||||
| -rw-r--r-- | drivers/message/i2o/core.h | 30 | ||||
| -rw-r--r-- | drivers/message/i2o/debug.c | 166 | ||||
| -rw-r--r-- | drivers/message/i2o/device.c | 440 | ||||
| -rw-r--r-- | drivers/message/i2o/driver.c | 66 | ||||
| -rw-r--r-- | drivers/message/i2o/exec-osm.c | 309 | ||||
| -rw-r--r-- | drivers/message/i2o/i2o_block.c | 421 | ||||
| -rw-r--r-- | drivers/message/i2o/i2o_block.h | 6 | ||||
| -rw-r--r-- | drivers/message/i2o/i2o_config.c | 412 | ||||
| -rw-r--r-- | drivers/message/i2o/i2o_lan.h | 159 | ||||
| -rw-r--r-- | drivers/message/i2o/i2o_proc.c | 219 | ||||
| -rw-r--r-- | drivers/message/i2o/i2o_scsi.c | 160 | ||||
| -rw-r--r-- | drivers/message/i2o/iop.c | 479 | ||||
| -rw-r--r-- | drivers/message/i2o/memory.c | 313 | ||||
| -rw-r--r-- | drivers/message/i2o/pci.c | 83 |
20 files changed, 1730 insertions, 1628 deletions
diff --git a/drivers/message/i2o/Kconfig b/drivers/message/i2o/Kconfig index 43a942a29c2..5afa0e393ec 100644 --- a/drivers/message/i2o/Kconfig +++ b/drivers/message/i2o/Kconfig @@ -1,8 +1,6 @@ -menu "I2O device support" - -config I2O - tristate "I2O support" +menuconfig I2O + tristate "I2O device support" depends on PCI ---help--- The Intelligent Input/Output (I2O) architecture allows hardware @@ -24,9 +22,21 @@ config I2O If unsure, say N. +if I2O + +config I2O_LCT_NOTIFY_ON_CHANGES + bool "Enable LCT notification" + default y + ---help--- + Only say N here if you have a I2O controller from SUN. The SUN + firmware doesn't support LCT notification on changes. If this option + is enabled on such a controller the driver will hang up in a endless + loop. On all other controllers say Y. + + If unsure, say Y. + config I2O_EXT_ADAPTEC bool "Enable Adaptec extensions" - depends on I2O default y ---help--- Say Y for support of raidutils for Adaptec I2O controllers. You also @@ -44,7 +54,7 @@ config I2O_EXT_ADAPTEC_DMA64 config I2O_CONFIG tristate "I2O Configuration support" - depends on I2O + depends on VIRT_TO_BUS ---help--- Say Y for support of the configuration interface for the I2O adapters. If you have a RAID controller from Adaptec and you want to use the @@ -65,7 +75,6 @@ config I2O_CONFIG_OLD_IOCTL config I2O_BUS tristate "I2O Bus Adapter OSM" - depends on I2O ---help--- Include support for the I2O Bus Adapter OSM. The Bus Adapter OSM provides access to the busses on the I2O controller. The main purpose @@ -76,7 +85,7 @@ config I2O_BUS config I2O_BLOCK tristate "I2O Block OSM" - depends on I2O + depends on BLOCK ---help--- Include support for the I2O Block OSM. The Block OSM presents disk and other structured block devices to the operating system. If you @@ -89,7 +98,7 @@ config I2O_BLOCK config I2O_SCSI tristate "I2O SCSI OSM" - depends on I2O && SCSI + depends on SCSI ---help--- Allows direct SCSI access to SCSI devices on a SCSI or FibreChannel I2O controller. You can use both the SCSI and Block OSM together if @@ -101,7 +110,6 @@ config I2O_SCSI config I2O_PROC tristate "I2O /proc support" - depends on I2O ---help--- If you say Y here and to "/proc file system support", you will be able to read I2O related information from the virtual directory @@ -110,5 +118,4 @@ config I2O_PROC To compile this support as a module, choose M here: the module will be called i2o_proc. -endmenu - +endif # I2O diff --git a/drivers/message/i2o/Makefile b/drivers/message/i2o/Makefile index 2c2e39aa1ef..b0982dacfd0 100644 --- a/drivers/message/i2o/Makefile +++ b/drivers/message/i2o/Makefile @@ -5,7 +5,7 @@ # In the future, some of these should be built conditionally. # -i2o_core-y += iop.o driver.o device.o debug.o pci.o exec-osm.o +i2o_core-y += iop.o driver.o device.o debug.o pci.o exec-osm.o memory.o i2o_bus-y += bus-osm.o i2o_config-y += config-osm.o obj-$(CONFIG_I2O) += i2o_core.o diff --git a/drivers/message/i2o/README b/drivers/message/i2o/README index a81f851f7b5..f072a8eb304 100644 --- a/drivers/message/i2o/README +++ b/drivers/message/i2o/README @@ -30,13 +30,13 @@ Juha Sievanen, University of Helsinki Finland Bug fixes Core code extensions -Auvo Häkkinen, University of Helsinki Finland +Auvo Häkkinen, University of Helsinki Finland LAN OSM code /Proc interface to LAN class Bug fixes Core code extensions -Taneli Vähäkangas, University of Helsinki Finland +Taneli Vähäkangas, University of Helsinki Finland Fixes to i2o_config CREDITS @@ -53,7 +53,7 @@ Symbios Logic (Now LSI) BoxHill Corporation Loan of initial FibreChannel disk array used for development work. -European Comission +European Commission Funding the work done by the University of Helsinki SysKonnect diff --git a/drivers/message/i2o/README.ioctl b/drivers/message/i2o/README.ioctl index 73dd084c0e9..4a7d2ebdfc9 100644 --- a/drivers/message/i2o/README.ioctl +++ b/drivers/message/i2o/README.ioctl @@ -110,7 +110,7 @@ V. Getting Logical Configuration Table ENOBUFS Buffer not large enough. If this occurs, the required buffer length is written into *(lct->reslen) -VI. Settting Parameters +VI. Setting Parameters SYNOPSIS @@ -138,7 +138,7 @@ VI. Settting Parameters The return value is the size in bytes of the data written into ops->resbuf if no errors occur. If an error occurs, -1 is returned - and errno is set appropriatly: + and errno is set appropriately: EFAULT Invalid user space pointer was passed ENXIO Invalid IOP number @@ -185,7 +185,7 @@ VII. Getting Parameters ENOMEM Kernel memory allocation error A return value of 0 does not mean that the value was actually - properly retreived. The user should check the result list + properly retrieved. The user should check the result list to determine the specific status of the transaction. VIII. Downloading Software @@ -222,7 +222,7 @@ VIII. Downloading Software RETURNS This function returns 0 no errors occur. If an error occurs, -1 - is returned and errno is set appropriatly: + is returned and errno is set appropriately: EFAULT Invalid user space pointer was passed ENXIO Invalid IOP number @@ -264,7 +264,7 @@ IX. Uploading Software RETURNS This function returns 0 if no errors occur. If an error occurs, -1 - is returned and errno is set appropriatly: + is returned and errno is set appropriately: EFAULT Invalid user space pointer was passed ENXIO Invalid IOP number @@ -301,7 +301,7 @@ X. Removing Software RETURNS This function returns 0 if no errors occur. If an error occurs, -1 - is returned and errno is set appropriatly: + is returned and errno is set appropriately: EFAULT Invalid user space pointer was passed ENXIO Invalid IOP number @@ -325,7 +325,7 @@ X. Validating Configuration RETURNS This function returns 0 if no erro occur. If an error occurs, -1 is - returned and errno is set appropriatly: + returned and errno is set appropriately: ETIMEDOUT Timeout waiting for reply message ENXIO Invalid IOP number @@ -360,7 +360,7 @@ XI. Configuration Dialog RETURNS This function returns 0 if no error occur. If an error occurs, -1 - is returned and errno is set appropriatly: + is returned and errno is set appropriately: EFAULT Invalid user space pointer was passed ENXIO Invalid IOP number diff --git a/drivers/message/i2o/bus-osm.c b/drivers/message/i2o/bus-osm.c index 151b228e1cb..c463dc2efc0 100644 --- a/drivers/message/i2o/bus-osm.c +++ b/drivers/message/i2o/bus-osm.c @@ -17,7 +17,7 @@ #include <linux/i2o.h> #define OSM_NAME "bus-osm" -#define OSM_VERSION "$Rev$" +#define OSM_VERSION "1.317" #define OSM_DESCRIPTION "I2O Bus Adapter OSM" static struct i2o_driver i2o_bus_driver; @@ -39,28 +39,32 @@ static struct i2o_class_id i2o_bus_class_id[] = { */ static int i2o_bus_scan(struct i2o_device *dev) { - struct i2o_message __iomem *msg; - u32 m; + struct i2o_message *msg; - m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) + msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) return -ETIMEDOUT; - writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); - writel(I2O_CMD_BUS_SCAN << 24 | HOST_TID << 12 | dev->lct_data.tid, - &msg->u.head[1]); + msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_BUS_SCAN << 24 | HOST_TID << 12 | dev->lct_data. + tid); - return i2o_msg_post_wait(dev->iop, m, 60); + return i2o_msg_post_wait(dev->iop, msg, 60); }; /** * i2o_bus_store_scan - Scan the I2O Bus Adapter * @d: device which should be scanned + * @attr: device_attribute + * @buf: output buffer + * @count: buffer size * * Returns count. */ -static ssize_t i2o_bus_store_scan(struct device *d, struct device_attribute *attr, const char *buf, - size_t count) +static ssize_t i2o_bus_store_scan(struct device *d, + struct device_attribute *attr, + const char *buf, size_t count) { struct i2o_device *i2o_dev = to_i2o_device(d); int rc; @@ -79,18 +83,26 @@ static DEVICE_ATTR(scan, S_IWUSR, NULL, i2o_bus_store_scan); * @dev: device to verify if it is a I2O Bus Adapter device * * Because we want all Bus Adapters always return 0. + * Except when we fail. Then we are sad. * - * Returns 0. + * Returns 0, except when we fail to excel. */ static int i2o_bus_probe(struct device *dev) { struct i2o_device *i2o_dev = to_i2o_device(get_device(dev)); + int rc; - device_create_file(dev, &dev_attr_scan); + rc = device_create_file(dev, &dev_attr_scan); + if (rc) + goto err_out; osm_info("device added (TID: %03x)\n", i2o_dev->lct_data.tid); return 0; + +err_out: + put_device(dev); + return rc; }; /** diff --git a/drivers/message/i2o/config-osm.c b/drivers/message/i2o/config-osm.c index 10432f66520..3bba7aa82e5 100644 --- a/drivers/message/i2o/config-osm.c +++ b/drivers/message/i2o/config-osm.c @@ -22,7 +22,7 @@ #include <asm/uaccess.h> #define OSM_NAME "config-osm" -#define OSM_VERSION "1.248" +#define OSM_VERSION "1.323" #define OSM_DESCRIPTION "I2O Configuration OSM" /* access mode user rw */ diff --git a/drivers/message/i2o/core.h b/drivers/message/i2o/core.h index 9eefedb1621..91614f11f89 100644 --- a/drivers/message/i2o/core.h +++ b/drivers/message/i2o/core.h @@ -14,42 +14,56 @@ */ /* Exec-OSM */ -extern struct bus_type i2o_bus_type; - extern struct i2o_driver i2o_exec_driver; extern int i2o_exec_lct_get(struct i2o_controller *); extern int __init i2o_exec_init(void); -extern void __exit i2o_exec_exit(void); +extern void i2o_exec_exit(void); /* driver */ +extern struct bus_type i2o_bus_type; + extern int i2o_driver_dispatch(struct i2o_controller *, u32); extern int __init i2o_driver_init(void); -extern void __exit i2o_driver_exit(void); +extern void i2o_driver_exit(void); /* PCI */ extern int __init i2o_pci_init(void); extern void __exit i2o_pci_exit(void); /* device */ +extern const struct attribute_group *i2o_device_groups[]; + extern void i2o_device_remove(struct i2o_device *); extern int i2o_device_parse_lct(struct i2o_controller *); +int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, + int oplen, void *reslist, int reslen); + /* IOP */ extern struct i2o_controller *i2o_iop_alloc(void); -extern void i2o_iop_free(struct i2o_controller *); + +/** + * i2o_iop_free - Free the i2o_controller struct + * @c: I2O controller to free + */ +static inline void i2o_iop_free(struct i2o_controller *c) +{ + i2o_pool_free(&c->in_msg); + kfree(c); +} extern int i2o_iop_add(struct i2o_controller *); extern void i2o_iop_remove(struct i2o_controller *); -/* config */ -extern int i2o_parm_issue(struct i2o_device *, int, void *, int, void *, int); - /* control registers relative to c->base */ #define I2O_IRQ_STATUS 0x30 #define I2O_IRQ_MASK 0x34 #define I2O_IN_PORT 0x40 #define I2O_OUT_PORT 0x44 +/* Motorola/Freescale specific register offset */ +#define I2O_MOTOROLA_PORT_OFFSET 0x10400 + #define I2O_IRQ_OUTBOUND_POST 0x00000008 diff --git a/drivers/message/i2o/debug.c b/drivers/message/i2o/debug.c index 40d4ea898db..ce62d8bfe1c 100644 --- a/drivers/message/i2o/debug.c +++ b/drivers/message/i2o/debug.c @@ -1,4 +1,3 @@ -#include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/pci.h> @@ -25,7 +24,7 @@ void i2o_report_status(const char *severity, const char *str, if (cmd == I2O_CMD_UTIL_EVT_REGISTER) return; // No status in this reply - printk(KERN_DEBUG "%s%s: ", severity, str); + printk("%s%s: ", severity, str); if (cmd < 0x1F) // Utility cmd i2o_report_util_cmd(cmd); @@ -33,7 +32,7 @@ void i2o_report_status(const char *severity, const char *str, else if (cmd >= 0xA0 && cmd <= 0xEF) // Executive cmd i2o_report_exec_cmd(cmd); else - printk(KERN_DEBUG "Cmd = %0#2x, ", cmd); // Other cmds + printk("Cmd = %0#2x, ", cmd); // Other cmds if (msg[0] & MSG_FAIL) { i2o_report_fail_status(req_status, msg); @@ -45,7 +44,7 @@ void i2o_report_status(const char *severity, const char *str, if (cmd < 0x1F || (cmd >= 0xA0 && cmd <= 0xEF)) i2o_report_common_dsc(detailed_status); else - printk(KERN_DEBUG " / DetailedStatus = %0#4x.\n", + printk(" / DetailedStatus = %0#4x.\n", detailed_status); } @@ -90,10 +89,10 @@ static void i2o_report_fail_status(u8 req_status, u32 * msg) }; if (req_status == I2O_FSC_TRANSPORT_UNKNOWN_FAILURE) - printk(KERN_DEBUG "TRANSPORT_UNKNOWN_FAILURE (%0#2x).\n", + printk("TRANSPORT_UNKNOWN_FAILURE (%0#2x).\n", req_status); else - printk(KERN_DEBUG "TRANSPORT_%s.\n", + printk("TRANSPORT_%s.\n", FAIL_STATUS[req_status & 0x0F]); /* Dump some details */ @@ -105,7 +104,7 @@ static void i2o_report_fail_status(u8 req_status, u32 * msg) printk(KERN_ERR " FailingHostUnit = 0x%04X, FailingIOP = 0x%03X\n", msg[5] >> 16, msg[5] & 0xFFF); - printk(KERN_ERR " Severity: 0x%02X ", (msg[4] >> 16) & 0xFF); + printk(KERN_ERR " Severity: 0x%02X\n", (msg[4] >> 16) & 0xFF); if (msg[4] & (1 << 16)) printk(KERN_DEBUG "(FormatError), " "this msg can never be delivered/processed.\n"); @@ -143,9 +142,9 @@ static void i2o_report_common_status(u8 req_status) }; if (req_status >= ARRAY_SIZE(REPLY_STATUS)) - printk(KERN_DEBUG "RequestStatus = %0#2x", req_status); + printk("RequestStatus = %0#2x", req_status); else - printk(KERN_DEBUG "%s", REPLY_STATUS[req_status]); + printk("%s", REPLY_STATUS[req_status]); } /* @@ -188,10 +187,10 @@ static void i2o_report_common_dsc(u16 detailed_status) }; if (detailed_status > I2O_DSC_DEVICE_NOT_AVAILABLE) - printk(KERN_DEBUG " / DetailedStatus = %0#4x.\n", + printk(" / DetailedStatus = %0#4x.\n", detailed_status); else - printk(KERN_DEBUG " / %s.\n", COMMON_DSC[detailed_status]); + printk(" / %s.\n", COMMON_DSC[detailed_status]); } /* @@ -201,49 +200,49 @@ static void i2o_report_util_cmd(u8 cmd) { switch (cmd) { case I2O_CMD_UTIL_NOP: - printk(KERN_DEBUG "UTIL_NOP, "); + printk("UTIL_NOP, "); break; case I2O_CMD_UTIL_ABORT: - printk(KERN_DEBUG "UTIL_ABORT, "); + printk("UTIL_ABORT, "); break; case I2O_CMD_UTIL_CLAIM: - printk(KERN_DEBUG "UTIL_CLAIM, "); + printk("UTIL_CLAIM, "); break; case I2O_CMD_UTIL_RELEASE: - printk(KERN_DEBUG "UTIL_CLAIM_RELEASE, "); + printk("UTIL_CLAIM_RELEASE, "); break; case I2O_CMD_UTIL_CONFIG_DIALOG: - printk(KERN_DEBUG "UTIL_CONFIG_DIALOG, "); + printk("UTIL_CONFIG_DIALOG, "); break; case I2O_CMD_UTIL_DEVICE_RESERVE: - printk(KERN_DEBUG "UTIL_DEVICE_RESERVE, "); + printk("UTIL_DEVICE_RESERVE, "); break; case I2O_CMD_UTIL_DEVICE_RELEASE: - printk(KERN_DEBUG "UTIL_DEVICE_RELEASE, "); + printk("UTIL_DEVICE_RELEASE, "); break; case I2O_CMD_UTIL_EVT_ACK: - printk(KERN_DEBUG "UTIL_EVENT_ACKNOWLEDGE, "); + printk("UTIL_EVENT_ACKNOWLEDGE, "); break; case I2O_CMD_UTIL_EVT_REGISTER: - printk(KERN_DEBUG "UTIL_EVENT_REGISTER, "); + printk("UTIL_EVENT_REGISTER, "); break; case I2O_CMD_UTIL_LOCK: - printk(KERN_DEBUG "UTIL_LOCK, "); + printk("UTIL_LOCK, "); break; case I2O_CMD_UTIL_LOCK_RELEASE: - printk(KERN_DEBUG "UTIL_LOCK_RELEASE, "); + printk("UTIL_LOCK_RELEASE, "); break; case I2O_CMD_UTIL_PARAMS_GET: - printk(KERN_DEBUG "UTIL_PARAMS_GET, "); + printk("UTIL_PARAMS_GET, "); break; case I2O_CMD_UTIL_PARAMS_SET: - printk(KERN_DEBUG "UTIL_PARAMS_SET, "); + printk("UTIL_PARAMS_SET, "); break; case I2O_CMD_UTIL_REPLY_FAULT_NOTIFY: - printk(KERN_DEBUG "UTIL_REPLY_FAULT_NOTIFY, "); + printk("UTIL_REPLY_FAULT_NOTIFY, "); break; default: - printk(KERN_DEBUG "Cmd = %0#2x, ", cmd); + printk("Cmd = %0#2x, ", cmd); } } @@ -254,106 +253,106 @@ static void i2o_report_exec_cmd(u8 cmd) { switch (cmd) { case I2O_CMD_ADAPTER_ASSIGN: - printk(KERN_DEBUG "EXEC_ADAPTER_ASSIGN, "); + printk("EXEC_ADAPTER_ASSIGN, "); break; case I2O_CMD_ADAPTER_READ: - printk(KERN_DEBUG "EXEC_ADAPTER_READ, "); + printk("EXEC_ADAPTER_READ, "); break; case I2O_CMD_ADAPTER_RELEASE: - printk(KERN_DEBUG "EXEC_ADAPTER_RELEASE, "); + printk("EXEC_ADAPTER_RELEASE, "); break; case I2O_CMD_BIOS_INFO_SET: - printk(KERN_DEBUG "EXEC_BIOS_INFO_SET, "); + printk("EXEC_BIOS_INFO_SET, "); break; case I2O_CMD_BOOT_DEVICE_SET: - printk(KERN_DEBUG "EXEC_BOOT_DEVICE_SET, "); + printk("EXEC_BOOT_DEVICE_SET, "); break; case I2O_CMD_CONFIG_VALIDATE: - printk(KERN_DEBUG "EXEC_CONFIG_VALIDATE, "); + printk("EXEC_CONFIG_VALIDATE, "); break; case I2O_CMD_CONN_SETUP: - printk(KERN_DEBUG "EXEC_CONN_SETUP, "); + printk("EXEC_CONN_SETUP, "); break; case I2O_CMD_DDM_DESTROY: - printk(KERN_DEBUG "EXEC_DDM_DESTROY, "); + printk("EXEC_DDM_DESTROY, "); break; case I2O_CMD_DDM_ENABLE: - printk(KERN_DEBUG "EXEC_DDM_ENABLE, "); + printk("EXEC_DDM_ENABLE, "); break; case I2O_CMD_DDM_QUIESCE: - printk(KERN_DEBUG "EXEC_DDM_QUIESCE, "); + printk("EXEC_DDM_QUIESCE, "); break; case I2O_CMD_DDM_RESET: - printk(KERN_DEBUG "EXEC_DDM_RESET, "); + printk("EXEC_DDM_RESET, "); break; case I2O_CMD_DDM_SUSPEND: - printk(KERN_DEBUG "EXEC_DDM_SUSPEND, "); + printk("EXEC_DDM_SUSPEND, "); break; case I2O_CMD_DEVICE_ASSIGN: - printk(KERN_DEBUG "EXEC_DEVICE_ASSIGN, "); + printk("EXEC_DEVICE_ASSIGN, "); break; case I2O_CMD_DEVICE_RELEASE: - printk(KERN_DEBUG "EXEC_DEVICE_RELEASE, "); + printk("EXEC_DEVICE_RELEASE, "); break; case I2O_CMD_HRT_GET: - printk(KERN_DEBUG "EXEC_HRT_GET, "); + printk("EXEC_HRT_GET, "); break; case I2O_CMD_ADAPTER_CLEAR: - printk(KERN_DEBUG "EXEC_IOP_CLEAR, "); + printk("EXEC_IOP_CLEAR, "); break; case I2O_CMD_ADAPTER_CONNECT: - printk(KERN_DEBUG "EXEC_IOP_CONNECT, "); + printk("EXEC_IOP_CONNECT, "); break; case I2O_CMD_ADAPTER_RESET: - printk(KERN_DEBUG "EXEC_IOP_RESET, "); + printk("EXEC_IOP_RESET, "); break; case I2O_CMD_LCT_NOTIFY: - printk(KERN_DEBUG "EXEC_LCT_NOTIFY, "); + printk("EXEC_LCT_NOTIFY, "); break; case I2O_CMD_OUTBOUND_INIT: - printk(KERN_DEBUG "EXEC_OUTBOUND_INIT, "); + printk("EXEC_OUTBOUND_INIT, "); break; case I2O_CMD_PATH_ENABLE: - printk(KERN_DEBUG "EXEC_PATH_ENABLE, "); + printk("EXEC_PATH_ENABLE, "); break; case I2O_CMD_PATH_QUIESCE: - printk(KERN_DEBUG "EXEC_PATH_QUIESCE, "); + printk("EXEC_PATH_QUIESCE, "); break; case I2O_CMD_PATH_RESET: - printk(KERN_DEBUG "EXEC_PATH_RESET, "); + printk("EXEC_PATH_RESET, "); break; case I2O_CMD_STATIC_MF_CREATE: - printk(KERN_DEBUG "EXEC_STATIC_MF_CREATE, "); + printk("EXEC_STATIC_MF_CREATE, "); break; case I2O_CMD_STATIC_MF_RELEASE: - printk(KERN_DEBUG "EXEC_STATIC_MF_RELEASE, "); + printk("EXEC_STATIC_MF_RELEASE, "); break; case I2O_CMD_STATUS_GET: - printk(KERN_DEBUG "EXEC_STATUS_GET, "); + printk("EXEC_STATUS_GET, "); break; case I2O_CMD_SW_DOWNLOAD: - printk(KERN_DEBUG "EXEC_SW_DOWNLOAD, "); + printk("EXEC_SW_DOWNLOAD, "); break; case I2O_CMD_SW_UPLOAD: - printk(KERN_DEBUG "EXEC_SW_UPLOAD, "); + printk("EXEC_SW_UPLOAD, "); break; case I2O_CMD_SW_REMOVE: - printk(KERN_DEBUG "EXEC_SW_REMOVE, "); + printk("EXEC_SW_REMOVE, "); break; case I2O_CMD_SYS_ENABLE: - printk(KERN_DEBUG "EXEC_SYS_ENABLE, "); + printk("EXEC_SYS_ENABLE, "); break; case I2O_CMD_SYS_MODIFY: - printk(KERN_DEBUG "EXEC_SYS_MODIFY, "); + printk("EXEC_SYS_MODIFY, "); break; case I2O_CMD_SYS_QUIESCE: - printk(KERN_DEBUG "EXEC_SYS_QUIESCE, "); + printk("EXEC_SYS_QUIESCE, "); break; case I2O_CMD_SYS_TAB_SET: - printk(KERN_DEBUG "EXEC_SYS_TAB_SET, "); + printk("EXEC_SYS_TAB_SET, "); break; default: - printk(KERN_DEBUG "Cmd = %#02x, ", cmd); + printk("Cmd = %#02x, ", cmd); } } @@ -362,28 +361,28 @@ void i2o_debug_state(struct i2o_controller *c) printk(KERN_INFO "%s: State = ", c->name); switch (((i2o_status_block *) c->status_block.virt)->iop_state) { case 0x01: - printk(KERN_DEBUG "INIT\n"); + printk("INIT\n"); break; case 0x02: - printk(KERN_DEBUG "RESET\n"); + printk("RESET\n"); break; case 0x04: - printk(KERN_DEBUG "HOLD\n"); + printk("HOLD\n"); break; case 0x05: - printk(KERN_DEBUG "READY\n"); + printk("READY\n"); break; case 0x08: - printk(KERN_DEBUG "OPERATIONAL\n"); + printk("OPERATIONAL\n"); break; case 0x10: - printk(KERN_DEBUG "FAILED\n"); + printk("FAILED\n"); break; case 0x11: - printk(KERN_DEBUG "FAULTED\n"); + printk("FAULTED\n"); break; default: - printk(KERN_DEBUG "%x (unknown !!)\n", + printk("%x (unknown !!)\n", ((i2o_status_block *) c->status_block.virt)->iop_state); } }; @@ -419,58 +418,53 @@ void i2o_dump_hrt(struct i2o_controller *c) d = (u8 *) (rows + 2); state = p[1] << 8 | p[0]; - printk(KERN_DEBUG "TID %04X:[", state & 0xFFF); + printk("TID %04X:[", state & 0xFFF); state >>= 12; if (state & (1 << 0)) - printk(KERN_DEBUG "H"); /* Hidden */ + printk("H"); /* Hidden */ if (state & (1 << 2)) { - printk(KERN_DEBUG "P"); /* Present */ + printk("P"); /* Present */ if (state & (1 << 1)) - printk(KERN_DEBUG "C"); /* Controlled */ + printk("C"); /* Controlled */ } if (state > 9) - printk(KERN_DEBUG "*"); /* Hard */ + printk("*"); /* Hard */ - printk(KERN_DEBUG "]:"); + printk("]:"); switch (p[3] & 0xFFFF) { case 0: /* Adapter private bus - easy */ - printk(KERN_DEBUG - "Local bus %d: I/O at 0x%04X Mem 0x%08X", p[2], + printk("Local bus %d: I/O at 0x%04X Mem 0x%08X", p[2], d[1] << 8 | d[0], *(u32 *) (d + 4)); break; case 1: /* ISA bus */ - printk(KERN_DEBUG - "ISA %d: CSN %d I/O at 0x%04X Mem 0x%08X", p[2], + printk("ISA %d: CSN %d I/O at 0x%04X Mem 0x%08X", p[2], d[2], d[1] << 8 | d[0], *(u32 *) (d + 4)); break; case 2: /* EISA bus */ - printk(KERN_DEBUG - "EISA %d: Slot %d I/O at 0x%04X Mem 0x%08X", + printk("EISA %d: Slot %d I/O at 0x%04X Mem 0x%08X", p[2], d[3], d[1] << 8 | d[0], *(u32 *) (d + 4)); break; case 3: /* MCA bus */ - printk(KERN_DEBUG - "MCA %d: Slot %d I/O at 0x%04X Mem 0x%08X", p[2], + printk("MCA %d: Slot %d I/O at 0x%04X Mem 0x%08X", p[2], d[3], d[1] << 8 | d[0], *(u32 *) (d + 4)); break; case 4: /* PCI bus */ - printk(KERN_DEBUG - "PCI %d: Bus %d Device %d Function %d", p[2], + printk("PCI %d: Bus %d Device %d Function %d", p[2], d[2], d[1], d[0]); break; case 0x80: /* Other */ default: - printk(KERN_DEBUG "Unsupported bus type."); + printk("Unsupported bus type."); break; } - printk(KERN_DEBUG "\n"); + printk("\n"); rows += length; } } diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c index 8eb50cdb8ae..98348f420b5 100644 --- a/drivers/message/i2o/device.c +++ b/drivers/message/i2o/device.c @@ -35,44 +35,43 @@ static inline int i2o_device_issue_claim(struct i2o_device *dev, u32 cmd, u32 type) { - struct i2o_message __iomem *msg; - u32 m; + struct i2o_message *msg; - m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -ETIMEDOUT; + msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); - writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); - writel(cmd << 24 | HOST_TID << 12 | dev->lct_data.tid, &msg->u.head[1]); - writel(type, &msg->body[0]); + msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(cmd << 24 | HOST_TID << 12 | dev->lct_data.tid); + msg->body[0] = cpu_to_le32(type); - return i2o_msg_post_wait(dev->iop, m, 60); + return i2o_msg_post_wait(dev->iop, msg, 60); } /** * i2o_device_claim - claim a device for use by an OSM * @dev: I2O device to claim - * @drv: I2O driver which wants to claim the device * - * Do the leg work to assign a device to a given OSM. If the claim succeed - * the owner of the rimary. If the attempt fails a negative errno code + * Do the leg work to assign a device to a given OSM. If the claim succeeds, + * the owner is the primary. If the attempt fails a negative errno code * is returned. On success zero is returned. */ int i2o_device_claim(struct i2o_device *dev) { int rc = 0; - down(&dev->lock); + mutex_lock(&dev->lock); rc = i2o_device_issue_claim(dev, I2O_CMD_UTIL_CLAIM, I2O_CLAIM_PRIMARY); if (!rc) - pr_debug("i2o: claim of device %d succeded\n", + pr_debug("i2o: claim of device %d succeeded\n", dev->lct_data.tid); else pr_debug("i2o: claim of device %d failed %d\n", dev->lct_data.tid, rc); - up(&dev->lock); + mutex_unlock(&dev->lock); return rc; } @@ -80,7 +79,6 @@ int i2o_device_claim(struct i2o_device *dev) /** * i2o_device_claim_release - release a device that the OSM is using * @dev: device to release - * @drv: driver which claimed the device * * Drop a claim by an OSM on a given I2O device. * @@ -96,7 +94,7 @@ int i2o_device_claim_release(struct i2o_device *dev) int tries; int rc = 0; - down(&dev->lock); + mutex_lock(&dev->lock); /* * If the controller takes a nonblocking approach to @@ -112,18 +110,17 @@ int i2o_device_claim_release(struct i2o_device *dev) } if (!rc) - pr_debug("i2o: claim release of device %d succeded\n", + pr_debug("i2o: claim release of device %d succeeded\n", dev->lct_data.tid); else pr_debug("i2o: claim release of device %d failed %d\n", dev->lct_data.tid, rc); - up(&dev->lock); + mutex_unlock(&dev->lock); return rc; } - /** * i2o_device_release - release the memory for a I2O device * @dev: I2O device which should be released @@ -135,50 +132,61 @@ static void i2o_device_release(struct device *dev) { struct i2o_device *i2o_dev = to_i2o_device(dev); - pr_debug("i2o: device %s released\n", dev->bus_id); + pr_debug("i2o: device %s released\n", dev_name(dev)); kfree(i2o_dev); } - /** - * i2o_device_class_show_class_id - Displays class id of I2O device - * @cd: class device of which the class id should be displayed + * class_id_show - Displays class id of I2O device + * @dev: device of which the class id should be displayed + * @attr: pointer to device attribute * @buf: buffer into which the class id should be printed * * Returns the number of bytes which are printed into the buffer. */ -static ssize_t i2o_device_show_class_id(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t class_id_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct i2o_device *i2o_dev = to_i2o_device(dev); sprintf(buf, "0x%03x\n", i2o_dev->lct_data.class_id); return strlen(buf) + 1; } +static DEVICE_ATTR_RO(class_id); /** - * i2o_device_class_show_tid - Displays TID of I2O device - * @cd: class device of which the TID should be displayed - * @buf: buffer into which the class id should be printed + * tid_show - Displays TID of I2O device + * @dev: device of which the TID should be displayed + * @attr: pointer to device attribute + * @buf: buffer into which the TID should be printed * * Returns the number of bytes which are printed into the buffer. */ -static ssize_t i2o_device_show_tid(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t tid_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct i2o_device *i2o_dev = to_i2o_device(dev); sprintf(buf, "0x%03x\n", i2o_dev->lct_data.tid); return strlen(buf) + 1; } +static DEVICE_ATTR_RO(tid); + +/* I2O device attributes */ +static struct attribute *i2o_device_attrs[] = { + &dev_attr_class_id.attr, + &dev_attr_tid.attr, + NULL, +}; -struct device_attribute i2o_device_attrs[] = { - __ATTR(class_id, S_IRUGO, i2o_device_show_class_id, NULL), - __ATTR(tid, S_IRUGO, i2o_device_show_tid, NULL), - __ATTR_NULL +static const struct attribute_group i2o_device_group = { + .attrs = i2o_device_attrs, +}; + +const struct attribute_group *i2o_device_groups[] = { + &i2o_device_group, + NULL, }; /** @@ -193,14 +201,12 @@ static struct i2o_device *i2o_device_alloc(void) { struct i2o_device *dev; - dev = kmalloc(sizeof(*dev), GFP_KERNEL); + dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) return ERR_PTR(-ENOMEM); - memset(dev, 0, sizeof(*dev)); - INIT_LIST_HEAD(&dev->list); - init_MUTEX(&dev->lock); + mutex_init(&dev->lock); dev->device.bus = &i2o_bus_type; dev->device.release = &i2o_device_release; @@ -209,111 +215,110 @@ static struct i2o_device *i2o_device_alloc(void) } /** - * i2o_setup_sysfs_links - Adds attributes to the I2O device - * @cd: I2O class device which is added to the I2O device class + * i2o_device_add - allocate a new I2O device and add it to the IOP + * @c: I2O controller that the device is on + * @entry: LCT entry of the I2O device * - * This function get called when a I2O device is added to the class. It - * creates the attributes for each device and creates user/parent symlink - * if necessary. + * Allocate a new I2O device and initialize it with the LCT entry. The + * device is appended to the device list of the controller. * - * Returns 0 on success or negative error code on failure. + * Returns zero on success, or a -ve errno. */ -static void i2o_setup_sysfs_links(struct i2o_device *i2o_dev) +static int i2o_device_add(struct i2o_controller *c, i2o_lct_entry *entry) { - struct i2o_controller *c = i2o_dev->iop; - struct i2o_device *tmp; + struct i2o_device *i2o_dev, *tmp; + int rc; + + i2o_dev = i2o_device_alloc(); + if (IS_ERR(i2o_dev)) { + printk(KERN_ERR "i2o: unable to allocate i2o device\n"); + return PTR_ERR(i2o_dev); + } + + i2o_dev->lct_data = *entry; + + dev_set_name(&i2o_dev->device, "%d:%03x", c->unit, + i2o_dev->lct_data.tid); + + i2o_dev->iop = c; + i2o_dev->device.parent = &c->device; + + rc = device_register(&i2o_dev->device); + if (rc) + goto err; + + list_add_tail(&i2o_dev->list, &c->devices); /* create user entries for this device */ tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid); - if (tmp && tmp != i2o_dev) - sysfs_create_link(&i2o_dev->device.kobj, - &tmp->device.kobj, "user"); + if (tmp && (tmp != i2o_dev)) { + rc = sysfs_create_link(&i2o_dev->device.kobj, + &tmp->device.kobj, "user"); + if (rc) + goto unreg_dev; + } - /* create user entries refering to this device */ + /* create user entries referring to this device */ list_for_each_entry(tmp, &c->devices, list) - if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid && - tmp != i2o_dev) - sysfs_create_link(&tmp->device.kobj, - &i2o_dev->device.kobj, "user"); + if ((tmp->lct_data.user_tid == i2o_dev->lct_data.tid) + && (tmp != i2o_dev)) { + rc = sysfs_create_link(&tmp->device.kobj, + &i2o_dev->device.kobj, "user"); + if (rc) + goto rmlink1; + } /* create parent entries for this device */ tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid); - if (tmp && tmp != i2o_dev) - sysfs_create_link(&i2o_dev->device.kobj, - &tmp->device.kobj, "parent"); + if (tmp && (tmp != i2o_dev)) { + rc = sysfs_create_link(&i2o_dev->device.kobj, + &tmp->device.kobj, "parent"); + if (rc) + goto rmlink1; + } - /* create parent entries refering to this device */ + /* create parent entries referring to this device */ list_for_each_entry(tmp, &c->devices, list) - if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid && - tmp != i2o_dev) - sysfs_create_link(&tmp->device.kobj, - &i2o_dev->device.kobj, "parent"); -} + if ((tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) + && (tmp != i2o_dev)) { + rc = sysfs_create_link(&tmp->device.kobj, + &i2o_dev->device.kobj, "parent"); + if (rc) + goto rmlink2; + } -static void i2o_remove_sysfs_links(struct i2o_device *i2o_dev) -{ - struct i2o_controller *c = i2o_dev->iop; - struct i2o_device *tmp; + i2o_driver_notify_device_add_all(i2o_dev); - sysfs_remove_link(&i2o_dev->device.kobj, "parent"); - sysfs_remove_link(&i2o_dev->device.kobj, "user"); + pr_debug("i2o: device %s added\n", dev_name(&i2o_dev->device)); + + return 0; +rmlink2: + /* If link creating failed halfway, we loop whole list to cleanup. + * And we don't care wrong removing of link, because sysfs_remove_link + * will take care of it. + */ list_for_each_entry(tmp, &c->devices, list) { if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) sysfs_remove_link(&tmp->device.kobj, "parent"); + } + sysfs_remove_link(&i2o_dev->device.kobj, "parent"); +rmlink1: + list_for_each_entry(tmp, &c->devices, list) if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid) sysfs_remove_link(&tmp->device.kobj, "user"); - } -} - - - -/** - * i2o_device_add - allocate a new I2O device and add it to the IOP - * @iop: I2O controller where the device is on - * @entry: LCT entry of the I2O device - * - * Allocate a new I2O device and initialize it with the LCT entry. The - * device is appended to the device list of the controller. - * - * Returns a pointer to the I2O device on success or negative error code - * on failure. - */ -static struct i2o_device *i2o_device_add(struct i2o_controller *c, - i2o_lct_entry * entry) -{ - struct i2o_device *dev; - - dev = i2o_device_alloc(); - if (IS_ERR(dev)) { - printk(KERN_ERR "i2o: unable to allocate i2o device\n"); - return dev; - } - - dev->lct_data = *entry; - dev->iop = c; - - snprintf(dev->device.bus_id, BUS_ID_SIZE, "%d:%03x", c->unit, - dev->lct_data.tid); - - dev->device.parent = &c->device; - - device_register(&dev->device); - - list_add_tail(&dev->list, &c->devices); - - i2o_setup_sysfs_links(dev); - - i2o_driver_notify_device_add_all(dev); - - pr_debug("i2o: device %s added\n", dev->device.bus_id); - - return dev; + sysfs_remove_link(&i2o_dev->device.kobj, "user"); +unreg_dev: + list_del(&i2o_dev->list); + device_unregister(&i2o_dev->device); +err: + kfree(i2o_dev); + return rc; } /** * i2o_device_remove - remove an I2O device from the I2O core - * @dev: I2O device which should be released + * @i2o_dev: I2O device which should be released * * Is used on I2O controller removal or LCT modification, when the device * is removed from the system. Note that the device could still hang @@ -321,9 +326,22 @@ static struct i2o_device *i2o_device_add(struct i2o_controller *c, */ void i2o_device_remove(struct i2o_device *i2o_dev) { + struct i2o_device *tmp; + struct i2o_controller *c = i2o_dev->iop; + i2o_driver_notify_device_remove_all(i2o_dev); - i2o_remove_sysfs_links(i2o_dev); + + sysfs_remove_link(&i2o_dev->device.kobj, "parent"); + sysfs_remove_link(&i2o_dev->device.kobj, "user"); + + list_for_each_entry(tmp, &c->devices, list) { + if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) + sysfs_remove_link(&tmp->device.kobj, "parent"); + if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid) + sysfs_remove_link(&tmp->device.kobj, "user"); + } list_del(&i2o_dev->list); + device_unregister(&i2o_dev->device); } @@ -341,56 +359,83 @@ int i2o_device_parse_lct(struct i2o_controller *c) { struct i2o_device *dev, *tmp; i2o_lct *lct; - int i; - int max; + u32 *dlct = c->dlct.virt; + int max = 0, i = 0; + u16 table_size; + u32 buf; - down(&c->lct_lock); + mutex_lock(&c->lct_lock); kfree(c->lct); - lct = c->dlct.virt; + buf = le32_to_cpu(*dlct++); + table_size = buf & 0xffff; - c->lct = kmalloc(lct->table_size * 4, GFP_KERNEL); - if (!c->lct) { - up(&c->lct_lock); + lct = c->lct = kmalloc(table_size * 4, GFP_KERNEL); + if (!lct) { + mutex_unlock(&c->lct_lock); return -ENOMEM; } - if (lct->table_size * 4 > c->dlct.len) { - memcpy(c->lct, c->dlct.virt, c->dlct.len); - up(&c->lct_lock); - return -EAGAIN; - } - - memcpy(c->lct, c->dlct.virt, lct->table_size * 4); + lct->lct_ver = buf >> 28; + lct->boot_tid = buf >> 16 & 0xfff; + lct->table_size = table_size; + lct->change_ind = le32_to_cpu(*dlct++); + lct->iop_flags = le32_to_cpu(*dlct++); - lct = c->lct; - - max = (lct->table_size - 3) / 9; + table_size -= 3; pr_debug("%s: LCT has %d entries (LCT size: %d)\n", c->name, max, lct->table_size); - /* remove devices, which are not in the LCT anymore */ - list_for_each_entry_safe(dev, tmp, &c->devices, list) { + while (table_size > 0) { + i2o_lct_entry *entry = &lct->lct_entry[max]; int found = 0; - for (i = 0; i < max; i++) { - if (lct->lct_entry[i].tid == dev->lct_data.tid) { + buf = le32_to_cpu(*dlct++); + entry->entry_size = buf & 0xffff; + entry->tid = buf >> 16 & 0xfff; + + entry->change_ind = le32_to_cpu(*dlct++); + entry->device_flags = le32_to_cpu(*dlct++); + + buf = le32_to_cpu(*dlct++); + entry->class_id = buf & 0xfff; + entry->version = buf >> 12 & 0xf; + entry->vendor_id = buf >> 16; + + entry->sub_class = le32_to_cpu(*dlct++); + + buf = le32_to_cpu(*dlct++); + entry->user_tid = buf & 0xfff; + entry->parent_tid = buf >> 12 & 0xfff; + entry->bios_info = buf >> 24; + + memcpy(&entry->identity_tag, dlct, 8); + dlct += 2; + + entry->event_capabilities = le32_to_cpu(*dlct++); + + /* add new devices, which are new in the LCT */ + list_for_each_entry_safe(dev, tmp, &c->devices, list) { + if (entry->tid == dev->lct_data.tid) { found = 1; break; } } if (!found) - i2o_device_remove(dev); + i2o_device_add(c, entry); + + table_size -= 9; + max++; } - /* add new devices, which are new in the LCT */ - for (i = 0; i < max; i++) { + /* remove devices, which are not in the LCT anymore */ + list_for_each_entry_safe(dev, tmp, &c->devices, list) { int found = 0; - list_for_each_entry_safe(dev, tmp, &c->devices, list) { + for (i = 0; i < max; i++) { if (lct->lct_entry[i].tid == dev->lct_data.tid) { found = 1; break; @@ -398,14 +443,14 @@ int i2o_device_parse_lct(struct i2o_controller *c) } if (!found) - i2o_device_add(c, &lct->lct_entry[i]); + i2o_device_remove(dev); } - up(&c->lct_lock); + + mutex_unlock(&c->lct_lock); return 0; } - /* * Run time support routines */ @@ -419,13 +464,9 @@ int i2o_device_parse_lct(struct i2o_controller *c) * ResultCount, ErrorInfoSize, BlockStatus and BlockSize. */ int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, - int oplen, void *reslist, int reslen) + int oplen, void *reslist, int reslen) { - struct i2o_message __iomem *msg; - u32 m; - u32 *res32 = (u32 *) reslist; - u32 *restmp = (u32 *) reslist; - int len = 0; + struct i2o_message *msg; int i = 0; int rc; struct i2o_dma res; @@ -434,29 +475,30 @@ int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, res.virt = NULL; - if (i2o_dma_alloc(dev, &res, reslen, GFP_KERNEL)) + if (i2o_dma_alloc(dev, &res, reslen)) return -ENOMEM; - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) { + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) { i2o_dma_free(dev, &res); - return -ETIMEDOUT; + return PTR_ERR(msg); } i = 0; - writel(cmd << 24 | HOST_TID << 12 | i2o_dev->lct_data.tid, - &msg->u.head[1]); - writel(0, &msg->body[i++]); - writel(0x4C000000 | oplen, &msg->body[i++]); /* OperationList */ - memcpy_toio(&msg->body[i], oplist, oplen); + msg->u.head[1] = + cpu_to_le32(cmd << 24 | HOST_TID << 12 | i2o_dev->lct_data.tid); + msg->body[i++] = cpu_to_le32(0x00000000); + msg->body[i++] = cpu_to_le32(0x4C000000 | oplen); /* OperationList */ + memcpy(&msg->body[i], oplist, oplen); i += (oplen / 4 + (oplen % 4 ? 1 : 0)); - writel(0xD0000000 | res.len, &msg->body[i++]); /* ResultList */ - writel(res.phys, &msg->body[i++]); + msg->body[i++] = cpu_to_le32(0xD0000000 | res.len); /* ResultList */ + msg->body[i++] = cpu_to_le32(res.phys); - writel(I2O_MESSAGE_SIZE(i + sizeof(struct i2o_message) / 4) | - SGL_OFFSET_5, &msg->u.head[0]); + msg->u.head[0] = + cpu_to_le32(I2O_MESSAGE_SIZE(i + sizeof(struct i2o_message) / 4) | + SGL_OFFSET_5); - rc = i2o_msg_post_wait_mem(c, m, 10, &res); + rc = i2o_msg_post_wait_mem(c, msg, 10, &res); /* This only looks like a memory leak - don't "fix" it. */ if (rc == -ETIMEDOUT) @@ -465,36 +507,7 @@ int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, memcpy(reslist, res.virt, res.len); i2o_dma_free(dev, &res); - /* Query failed */ - if (rc) - return rc; - /* - * Calculate number of bytes of Result LIST - * We need to loop through each Result BLOCK and grab the length - */ - restmp = res32 + 1; - len = 1; - for (i = 0; i < (res32[0] & 0X0000FFFF); i++) { - if (restmp[0] & 0x00FF0000) { /* BlockStatus != SUCCESS */ - printk(KERN_WARNING - "%s - Error:\n ErrorInfoSize = 0x%02x, " - "BlockStatus = 0x%02x, BlockSize = 0x%04x\n", - (cmd == - I2O_CMD_UTIL_PARAMS_SET) ? "PARAMS_SET" : - "PARAMS_GET", res32[1] >> 24, - (res32[1] >> 16) & 0xFF, res32[1] & 0xFFFF); - - /* - * If this is the only request,than we return an error - */ - if ((res32[0] & 0x0000FFFF) == 1) { - return -((res32[1] >> 16) & 0xFF); /* -BlockStatus */ - } - } - len += restmp[0] & 0x0000FFFF; /* Length of res BLOCK */ - restmp += restmp[0] & 0x0000FFFF; /* Skip to next BLOCK */ - } - return (len << 2); /* bytes used by result list */ + return rc; } /* @@ -503,28 +516,25 @@ int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field, void *buf, int buflen) { - u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field }; + u32 opblk[] = { cpu_to_le32(0x00000001), + cpu_to_le32((u16) group << 16 | I2O_PARAMS_FIELD_GET), + cpu_to_le32((s16) field << 16 | 0x00000001) + }; u8 *resblk; /* 8 bytes for header */ - int size; - - if (field == -1) /* whole group */ - opblk[4] = -1; + int rc; - resblk = kmalloc(buflen + 8, GFP_KERNEL | GFP_ATOMIC); + resblk = kmalloc(buflen + 8, GFP_KERNEL); if (!resblk) return -ENOMEM; - size = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk, - sizeof(opblk), resblk, buflen + 8); + rc = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk, + sizeof(opblk), resblk, buflen + 8); memcpy(buf, resblk + 8, buflen); /* cut off header */ kfree(resblk); - if (size > buflen) - return buflen; - - return size; + return rc; } /* @@ -534,12 +544,12 @@ int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field, * else return specific fields * ibuf contains fieldindexes * - * if oper == I2O_PARAMS_LIST_GET, get from specific rows - * if fieldcount == -1 return all fields + * if oper == I2O_PARAMS_LIST_GET, get from specific rows + * if fieldcount == -1 return all fields * ibuf contains rowcount, keyvalues - * else return specific fields + * else return specific fields * fieldcount is # of fieldindexes - * ibuf contains fieldindexes, rowcount, keyvalues + * ibuf contains fieldindexes, rowcount, keyvalues * * You could also use directly function i2o_issue_params(). */ diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c index 0fb9c4e2ad4..1b18a0d1d05 100644 --- a/drivers/message/i2o/driver.c +++ b/drivers/message/i2o/driver.c @@ -34,9 +34,7 @@ static spinlock_t i2o_drivers_lock; static struct i2o_driver **i2o_drivers; /** - * i2o_bus_match - Tell if a I2O device class id match the class ids of - * the I2O driver (OSM) - * + * i2o_bus_match - Tell if I2O device class id matches the class ids of the I2O driver (OSM) * @dev: device which should be verified * @drv: the driver to match against * @@ -61,12 +59,10 @@ static int i2o_bus_match(struct device *dev, struct device_driver *drv) }; /* I2O bus type */ -extern struct device_attribute i2o_device_attrs[]; - struct bus_type i2o_bus_type = { .name = "i2o", .match = i2o_bus_match, - .dev_attrs = i2o_device_attrs, + .dev_groups = i2o_device_groups, }; /** @@ -88,7 +84,8 @@ int i2o_driver_register(struct i2o_driver *drv) osm_debug("Register driver %s\n", drv->name); if (drv->event) { - drv->event_queue = create_workqueue(drv->name); + drv->event_queue = alloc_workqueue("%s", WQ_MEM_RECLAIM, 1, + drv->name); if (!drv->event_queue) { osm_err("Could not initialize event queue for driver " "%s\n", drv->name); @@ -108,7 +105,8 @@ int i2o_driver_register(struct i2o_driver *drv) osm_err("too many drivers registered, increase " "max_drivers\n"); spin_unlock_irqrestore(&i2o_drivers_lock, flags); - return -EFAULT; + rc = -EFAULT; + goto out; } drv->context = i; @@ -128,7 +126,14 @@ int i2o_driver_register(struct i2o_driver *drv) rc = driver_register(&drv->driver); if (rc) + goto out; + + return 0; +out: + if (drv->event_queue) { destroy_workqueue(drv->event_queue); + drv->event_queue = NULL; + } return rc; }; @@ -173,7 +178,6 @@ void i2o_driver_unregister(struct i2o_driver *drv) * i2o_driver_dispatch - dispatch an I2O reply message * @c: I2O controller of the message * @m: I2O message number - * @msg: I2O message to be delivered * * The reply is delivered to the driver from which the original message * was. This function is only called from interrupt context. @@ -219,14 +223,14 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m) /* cut of header from message size (in 32-bit words) */ size = (le32_to_cpu(msg->u.head[0]) >> 16) - 5; - evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC | __GFP_ZERO); + evt = kzalloc(size * 4 + sizeof(*evt), GFP_ATOMIC); if (!evt) return -ENOMEM; evt->size = size; evt->tcntxt = le32_to_cpu(msg->u.s.tcntxt); evt->event_indicator = le32_to_cpu(msg->body[0]); - memcpy(&evt->tcntxt, &msg->u.s.tcntxt, size * 4); + memcpy(&evt->data, &msg->body[1], size * 4); list_for_each_entry_safe(dev, tmp, &c->devices, list) if (dev->lct_data.tid == tid) { @@ -234,7 +238,7 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m) break; } - INIT_WORK(&evt->work, (void (*)(void *))drv->event, evt); + INIT_WORK(&evt->work, drv->event); queue_work(drv->event_queue, &evt->work); return 1; } @@ -250,7 +254,7 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m) /** * i2o_driver_notify_controller_add_all - Send notify of added controller - * to all I2O drivers + * @c: newly added controller * * Send notifications to all registered drivers that a new controller was * added. @@ -260,7 +264,7 @@ void i2o_driver_notify_controller_add_all(struct i2o_controller *c) int i; struct i2o_driver *drv; - for (i = 0; i < I2O_MAX_DRIVERS; i++) { + for (i = 0; i < i2o_max_drivers; i++) { drv = i2o_drivers[i]; if (drv) @@ -269,8 +273,8 @@ void i2o_driver_notify_controller_add_all(struct i2o_controller *c) } /** - * i2o_driver_notify_controller_remove_all - Send notify of removed - * controller to all I2O drivers + * i2o_driver_notify_controller_remove_all - Send notify of removed controller + * @c: controller that is being removed * * Send notifications to all registered drivers that a controller was * removed. @@ -280,7 +284,7 @@ void i2o_driver_notify_controller_remove_all(struct i2o_controller *c) int i; struct i2o_driver *drv; - for (i = 0; i < I2O_MAX_DRIVERS; i++) { + for (i = 0; i < i2o_max_drivers; i++) { drv = i2o_drivers[i]; if (drv) @@ -289,8 +293,8 @@ void i2o_driver_notify_controller_remove_all(struct i2o_controller *c) } /** - * i2o_driver_notify_device_add_all - Send notify of added device to all - * I2O drivers + * i2o_driver_notify_device_add_all - Send notify of added device + * @i2o_dev: newly added I2O device * * Send notifications to all registered drivers that a device was added. */ @@ -299,7 +303,7 @@ void i2o_driver_notify_device_add_all(struct i2o_device *i2o_dev) int i; struct i2o_driver *drv; - for (i = 0; i < I2O_MAX_DRIVERS; i++) { + for (i = 0; i < i2o_max_drivers; i++) { drv = i2o_drivers[i]; if (drv) @@ -308,8 +312,8 @@ void i2o_driver_notify_device_add_all(struct i2o_device *i2o_dev) } /** - * i2o_driver_notify_device_remove_all - Send notify of removed device to - * all I2O drivers + * i2o_driver_notify_device_remove_all - Send notify of removed device + * @i2o_dev: device that is being removed * * Send notifications to all registered drivers that a device was removed. */ @@ -318,7 +322,7 @@ void i2o_driver_notify_device_remove_all(struct i2o_device *i2o_dev) int i; struct i2o_driver *drv; - for (i = 0; i < I2O_MAX_DRIVERS; i++) { + for (i = 0; i < i2o_max_drivers; i++) { drv = i2o_drivers[i]; if (drv) @@ -339,22 +343,18 @@ int __init i2o_driver_init(void) spin_lock_init(&i2o_drivers_lock); - if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64) || - ((i2o_max_drivers ^ (i2o_max_drivers - 1)) != - (2 * i2o_max_drivers - 1))) { - osm_warn("max_drivers set to %d, but must be >=2 and <= 64 and " - "a power of 2\n", i2o_max_drivers); + if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64)) { + osm_warn("max_drivers set to %d, but must be >=2 and <= 64\n", + i2o_max_drivers); i2o_max_drivers = I2O_MAX_DRIVERS; } osm_info("max drivers = %d\n", i2o_max_drivers); i2o_drivers = - kmalloc(i2o_max_drivers * sizeof(*i2o_drivers), GFP_KERNEL); + kcalloc(i2o_max_drivers, sizeof(*i2o_drivers), GFP_KERNEL); if (!i2o_drivers) return -ENOMEM; - memset(i2o_drivers, 0, i2o_max_drivers * sizeof(*i2o_drivers)); - rc = bus_register(&i2o_bus_type); if (rc < 0) @@ -366,9 +366,9 @@ int __init i2o_driver_init(void) /** * i2o_driver_exit - clean up I2O drivers (OSMs) * - * Unregisters the I2O bus and free driver array. + * Unregisters the I2O bus and frees driver array. */ -void __exit i2o_driver_exit(void) +void i2o_driver_exit(void) { bus_unregister(&i2o_bus_type); kfree(i2o_drivers); diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c index 9c339a2505b..a3970e56ae5 100644 --- a/drivers/message/i2o/exec-osm.c +++ b/drivers/message/i2o/exec-osm.c @@ -15,11 +15,11 @@ * * Fixes/additions: * Philipp Rumpf - * Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI> - * Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI> + * Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI> + * Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI> * Deepak Saxena <deepak@plexity.net> * Boji T Kannanthanam <boji.t.kannanthanam@intel.com> - * Alan Cox <alan@redhat.com>: + * Alan Cox <alan@lxorguk.ukuu.org.uk>: * Ported to Linux 2.5. * Markus Lidel <Markus.Lidel@shadowconnect.com>: * Minor fixes for 2.6. @@ -33,7 +33,7 @@ #include <linux/workqueue.h> #include <linux/string.h> #include <linux/slab.h> -#include <linux/sched.h> /* wait_event_interruptible_timeout() needs this */ +#include <linux/sched.h> /* wait_event_interruptible_timeout() needs this */ #include <asm/param.h> /* HZ */ #include "core.h" @@ -41,8 +41,6 @@ struct i2o_driver i2o_exec_driver; -static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind); - /* global wait list for POST WAIT */ static LIST_HEAD(i2o_exec_wait_list); @@ -55,6 +53,14 @@ struct i2o_exec_wait { u32 m; /* message id */ struct i2o_message *msg; /* pointer to the reply message */ struct list_head list; /* node in global wait list */ + spinlock_t lock; /* lock before modifying */ +}; + +/* Work struct needed to handle LCT NOTIFY replies */ +struct i2o_exec_lct_notify_work { + struct work_struct work; /* work struct */ + struct i2o_controller *c; /* controller on which the LCT NOTIFY + was received */ }; /* Exec OSM class handling definition */ @@ -75,20 +81,19 @@ static struct i2o_exec_wait *i2o_exec_wait_alloc(void) { struct i2o_exec_wait *wait; - wait = kmalloc(sizeof(*wait), GFP_KERNEL); + wait = kzalloc(sizeof(*wait), GFP_KERNEL); if (!wait) - return ERR_PTR(-ENOMEM); - - memset(wait, 0, sizeof(*wait)); + return NULL; INIT_LIST_HEAD(&wait->list); + spin_lock_init(&wait->lock); return wait; }; /** - * i2o_exec_wait_free - Free a i2o_exec_wait struct - * @i2o_exec_wait: I2O wait data which should be cleaned up + * i2o_exec_wait_free - Free an i2o_exec_wait struct + * @wait: I2O wait data which should be cleaned up */ static void i2o_exec_wait_free(struct i2o_exec_wait *wait) { @@ -98,7 +103,7 @@ static void i2o_exec_wait_free(struct i2o_exec_wait *wait) /** * i2o_msg_post_wait_mem - Post and wait a message with DMA buffers * @c: controller - * @m: message to post + * @msg: message to post * @timeout: time in seconds to wait * @dma: i2o_dma struct of the DMA buffer to free on failure * @@ -114,18 +119,20 @@ static void i2o_exec_wait_free(struct i2o_exec_wait *wait) * Returns 0 on success, negative error code on timeout or positive error * code from reply. */ -int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long - timeout, struct i2o_dma *dma) +int i2o_msg_post_wait_mem(struct i2o_controller *c, struct i2o_message *msg, + unsigned long timeout, struct i2o_dma *dma) { - DECLARE_WAIT_QUEUE_HEAD(wq); + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); struct i2o_exec_wait *wait; static u32 tcntxt = 0x80000000; - struct i2o_message __iomem *msg = i2o_msg_in_to_virt(c, m); + unsigned long flags; int rc = 0; wait = i2o_exec_wait_alloc(); - if (!wait) + if (!wait) { + i2o_msg_nop(c, msg); return -ENOMEM; + } if (tcntxt == 0xffffffff) tcntxt = 0x80000000; @@ -138,37 +145,32 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long * We will only use transaction contexts >= 0x80000000 for POST WAIT, * so we could find a POST WAIT reply easier in the reply handler. */ - writel(i2o_exec_driver.context, &msg->u.s.icntxt); + msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context); wait->tcntxt = tcntxt++; - writel(wait->tcntxt, &msg->u.s.tcntxt); + msg->u.s.tcntxt = cpu_to_le32(wait->tcntxt); + + wait->wq = &wq; + /* + * we add elements to the head, because if a entry in the list will + * never be removed, we have to iterate over it every time + */ + list_add(&wait->list, &i2o_exec_wait_list); /* * Post the message to the controller. At some point later it will * return. If we time out before it returns then complete will be zero. */ - i2o_msg_post(c, m); - - if (!wait->complete) { - wait->wq = &wq; - /* - * we add elements add the head, because if a entry in the list - * will never be removed, we have to iterate over it every time - */ - list_add(&wait->list, &i2o_exec_wait_list); + i2o_msg_post(c, msg); - wait_event_interruptible_timeout(wq, wait->complete, - timeout * HZ); + wait_event_interruptible_timeout(wq, wait->complete, timeout * HZ); - wait->wq = NULL; - } + spin_lock_irqsave(&wait->lock, flags); - barrier(); + wait->wq = NULL; - if (wait->complete) { + if (wait->complete) rc = le32_to_cpu(wait->msg->body[0]) >> 24; - i2o_flush_reply(c, wait->m); - i2o_exec_wait_free(wait); - } else { + else { /* * We cannot remove it now. This is important. When it does * terminate (which it must do if the controller has not @@ -182,6 +184,13 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long rc = -ETIMEDOUT; } + spin_unlock_irqrestore(&wait->lock, flags); + + if (rc != -ETIMEDOUT) { + i2o_flush_reply(c, wait->m); + i2o_exec_wait_free(wait); + } + return rc; }; @@ -209,7 +218,6 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, { struct i2o_exec_wait *wait, *tmp; unsigned long flags; - static spinlock_t lock = SPIN_LOCK_UNLOCKED; int rc = 1; /* @@ -219,23 +227,24 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, * already expired. Not much we can do about that except log it for * debug purposes, increase timeout, and recompile. */ - spin_lock_irqsave(&lock, flags); list_for_each_entry_safe(wait, tmp, &i2o_exec_wait_list, list) { if (wait->tcntxt == context) { - list_del(&wait->list); + spin_lock_irqsave(&wait->lock, flags); - spin_unlock_irqrestore(&lock, flags); + list_del(&wait->list); wait->m = m; wait->msg = msg; wait->complete = 1; - barrier(); - - if (wait->wq) { - wake_up_interruptible(wait->wq); + if (wait->wq) rc = 0; - } else { + else + rc = -1; + + spin_unlock_irqrestore(&wait->lock, flags); + + if (rc) { struct device *dev; dev = &c->pdev->dev; @@ -244,15 +253,13 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, c->name); i2o_dma_free(dev, &wait->dma); i2o_exec_wait_free(wait); - rc = -1; - } + } else + wake_up_interruptible(wait->wq); return rc; } } - spin_unlock_irqrestore(&lock, flags); - osm_warn("%s: Bogus reply in POST WAIT (tr-context: %08x)!\n", c->name, context); @@ -262,17 +269,19 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, /** * i2o_exec_show_vendor_id - Displays Vendor ID of controller * @d: device of which the Vendor ID should be displayed + * @attr: device_attribute to display * @buf: buffer into which the Vendor ID should be printed * * Returns number of bytes printed into buffer. */ -static ssize_t i2o_exec_show_vendor_id(struct device *d, struct device_attribute *attr, char *buf) +static ssize_t i2o_exec_show_vendor_id(struct device *d, + struct device_attribute *attr, char *buf) { struct i2o_device *dev = to_i2o_device(d); u16 id; - if (i2o_parm_field_get(dev, 0x0000, 0, &id, 2)) { - sprintf(buf, "0x%04x", id); + if (!i2o_parm_field_get(dev, 0x0000, 0, &id, 2)) { + sprintf(buf, "0x%04x", le16_to_cpu(id)); return strlen(buf) + 1; } @@ -282,17 +291,20 @@ static ssize_t i2o_exec_show_vendor_id(struct device *d, struct device_attribute /** * i2o_exec_show_product_id - Displays Product ID of controller * @d: device of which the Product ID should be displayed + * @attr: device_attribute to display * @buf: buffer into which the Product ID should be printed * * Returns number of bytes printed into buffer. */ -static ssize_t i2o_exec_show_product_id(struct device *d, struct device_attribute *attr, char *buf) +static ssize_t i2o_exec_show_product_id(struct device *d, + struct device_attribute *attr, + char *buf) { struct i2o_device *dev = to_i2o_device(d); u16 id; - if (i2o_parm_field_get(dev, 0x0000, 1, &id, 2)) { - sprintf(buf, "0x%04x", id); + if (!i2o_parm_field_get(dev, 0x0000, 1, &id, 2)) { + sprintf(buf, "0x%04x", le16_to_cpu(id)); return strlen(buf) + 1; } @@ -315,18 +327,26 @@ static DEVICE_ATTR(product_id, S_IRUGO, i2o_exec_show_product_id, NULL); static int i2o_exec_probe(struct device *dev) { struct i2o_device *i2o_dev = to_i2o_device(dev); - struct i2o_controller *c = i2o_dev->iop; - - i2o_event_register(i2o_dev, &i2o_exec_driver, 0, 0xffffffff); + int rc; - c->exec = i2o_dev; + rc = i2o_event_register(i2o_dev, &i2o_exec_driver, 0, 0xffffffff); + if (rc) goto err_out; - i2o_exec_lct_notify(c, c->lct->change_ind + 1); + rc = device_create_file(dev, &dev_attr_vendor_id); + if (rc) goto err_evtreg; + rc = device_create_file(dev, &dev_attr_product_id); + if (rc) goto err_vid; - device_create_file(dev, &dev_attr_vendor_id); - device_create_file(dev, &dev_attr_product_id); + i2o_dev->iop->exec = i2o_dev; return 0; + +err_vid: + device_remove_file(dev, &dev_attr_vendor_id); +err_evtreg: + i2o_event_register(to_i2o_device(dev), &i2o_exec_driver, 0, 0); +err_out: + return rc; }; /** @@ -347,22 +367,80 @@ static int i2o_exec_remove(struct device *dev) return 0; }; +#ifdef CONFIG_I2O_LCT_NOTIFY_ON_CHANGES +/** + * i2o_exec_lct_notify - Send a asynchronus LCT NOTIFY request + * @c: I2O controller to which the request should be send + * @change_ind: change indicator + * + * This function sends a LCT NOTIFY request to the I2O controller with + * the change indicator change_ind. If the change_ind == 0 the controller + * replies immediately after the request. If change_ind > 0 the reply is + * send after change indicator of the LCT is > change_ind. + */ +static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind) +{ + i2o_status_block *sb = c->status_block.virt; + struct device *dev; + struct i2o_message *msg; + + mutex_lock(&c->lct_lock); + + dev = &c->pdev->dev; + + if (i2o_dma_realloc(dev, &c->dlct, + le32_to_cpu(sb->expected_lct_size))) { + mutex_unlock(&c->lct_lock); + return -ENOMEM; + } + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) { + mutex_unlock(&c->lct_lock); + return PTR_ERR(msg); + } + + msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6); + msg->u.head[1] = cpu_to_le32(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 | + ADAPTER_TID); + msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context); + msg->u.s.tcntxt = cpu_to_le32(0x00000000); + msg->body[0] = cpu_to_le32(0xffffffff); + msg->body[1] = cpu_to_le32(change_ind); + msg->body[2] = cpu_to_le32(0xd0000000 | c->dlct.len); + msg->body[3] = cpu_to_le32(c->dlct.phys); + + i2o_msg_post(c, msg); + + mutex_unlock(&c->lct_lock); + + return 0; +} +#endif + /** * i2o_exec_lct_modified - Called on LCT NOTIFY reply - * @c: I2O controller on which the LCT has modified + * @_work: work struct for a specific controller * * This function handles asynchronus LCT NOTIFY replies. It parses the * new LCT and if the buffer for the LCT was to small sends a LCT NOTIFY * again, otherwise send LCT NOTIFY to get informed on next LCT change. */ -static void i2o_exec_lct_modified(struct i2o_controller *c) +static void i2o_exec_lct_modified(struct work_struct *_work) { + struct i2o_exec_lct_notify_work *work = + container_of(_work, struct i2o_exec_lct_notify_work, work); u32 change_ind = 0; + struct i2o_controller *c = work->c; + + kfree(work); if (i2o_device_parse_lct(c) != -EAGAIN) change_ind = c->lct->change_ind + 1; +#ifdef CONFIG_I2O_LCT_NOTIFY_ON_CHANGES i2o_exec_lct_notify(c, change_ind); +#endif }; /** @@ -385,23 +463,22 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m, u32 context; if (le32_to_cpu(msg->u.head[0]) & MSG_FAIL) { + struct i2o_message __iomem *pmsg; + u32 pm; + /* * If Fail bit is set we must take the transaction context of * the preserved message to find the right request again. */ - struct i2o_message __iomem *pmsg; - u32 pm; pm = le32_to_cpu(msg->body[3]); - pmsg = i2o_msg_in_to_virt(c, pm); + context = readl(&pmsg->u.s.tcntxt); i2o_report_status(KERN_INFO, "i2o_core", msg); - context = readl(&pmsg->u.s.tcntxt); - /* Release the preserved msg */ - i2o_msg_nop(c, pm); + i2o_msg_nop_mfa(c, pm); } else context = le32_to_cpu(msg->u.s.tcntxt); @@ -409,7 +486,7 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m, return i2o_msg_post_wait_complete(c, m, msg, context); if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) { - struct work_struct *work; + struct i2o_exec_lct_notify_work *work; pr_debug("%s: LCT notify received\n", c->name); @@ -417,8 +494,10 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m, if (!work) return -ENOMEM; - INIT_WORK(work, (void (*)(void *))i2o_exec_lct_modified, c); - queue_work(i2o_exec_driver.event_queue, work); + work->c = c; + + INIT_WORK(&work->work, i2o_exec_lct_modified); + queue_work(i2o_exec_driver.event_queue, &work->work); return 1; } @@ -437,13 +516,15 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m, /** * i2o_exec_event - Event handling function - * @evt: Event which occurs + * @work: Work item in occurring event * * Handles events send by the Executive device. At the moment does not do * anything useful. */ -static void i2o_exec_event(struct i2o_event *evt) +static void i2o_exec_event(struct work_struct *work) { + struct i2o_event *evt = container_of(work, struct i2o_event, work); + if (likely(evt->i2o_dev)) osm_debug("Event received from device: %d\n", evt->i2o_dev->lct_data.tid); @@ -462,25 +543,26 @@ static void i2o_exec_event(struct i2o_event *evt) */ int i2o_exec_lct_get(struct i2o_controller *c) { - struct i2o_message __iomem *msg; - u32 m; + struct i2o_message *msg; int i = 0; int rc = -EAGAIN; for (i = 1; i <= I2O_LCT_GET_TRIES; i++) { - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -ETIMEDOUT; - - writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6, &msg->u.head[0]); - writel(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 | ADAPTER_TID, - &msg->u.head[1]); - writel(0xffffffff, &msg->body[0]); - writel(0x00000000, &msg->body[1]); - writel(0xd0000000 | c->dlct.len, &msg->body[2]); - writel(c->dlct.phys, &msg->body[3]); - - rc = i2o_msg_post_wait(c, m, I2O_TIMEOUT_LCT_GET); + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = + cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 | + ADAPTER_TID); + msg->body[0] = cpu_to_le32(0xffffffff); + msg->body[1] = cpu_to_le32(0x00000000); + msg->body[2] = cpu_to_le32(0xd0000000 | c->dlct.len); + msg->body[3] = cpu_to_le32(c->dlct.phys); + + rc = i2o_msg_post_wait(c, msg, I2O_TIMEOUT_LCT_GET); if (rc < 0) break; @@ -492,47 +574,6 @@ int i2o_exec_lct_get(struct i2o_controller *c) return rc; } -/** - * i2o_exec_lct_notify - Send a asynchronus LCT NOTIFY request - * @c: I2O controller to which the request should be send - * @change_ind: change indicator - * - * This function sends a LCT NOTIFY request to the I2O controller with - * the change indicator change_ind. If the change_ind == 0 the controller - * replies immediately after the request. If change_ind > 0 the reply is - * send after change indicator of the LCT is > change_ind. - */ -static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind) -{ - i2o_status_block *sb = c->status_block.virt; - struct device *dev; - struct i2o_message __iomem *msg; - u32 m; - - dev = &c->pdev->dev; - - if (i2o_dma_realloc(dev, &c->dlct, sb->expected_lct_size, GFP_KERNEL)) - return -ENOMEM; - - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -ETIMEDOUT; - - writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6, &msg->u.head[0]); - writel(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 | ADAPTER_TID, - &msg->u.head[1]); - writel(i2o_exec_driver.context, &msg->u.s.icntxt); - writel(0, &msg->u.s.tcntxt); /* FIXME */ - writel(0xffffffff, &msg->body[0]); - writel(change_ind, &msg->body[1]); - writel(0xd0000000 | c->dlct.len, &msg->body[2]); - writel(c->dlct.phys, &msg->body[3]); - - i2o_msg_post(c, m); - - return 0; -}; - /* Exec OSM driver struct */ struct i2o_driver i2o_exec_driver = { .name = OSM_NAME, @@ -562,7 +603,7 @@ int __init i2o_exec_init(void) * * Unregisters the Exec OSM from the I2O core. */ -void __exit i2o_exec_exit(void) +void i2o_exec_exit(void) { i2o_driver_unregister(&i2o_exec_driver); }; diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index f283b5bafdd..6fc3866965d 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c @@ -51,7 +51,9 @@ */ #include <linux/module.h> +#include <linux/slab.h> #include <linux/i2o.h> +#include <linux/mutex.h> #include <linux/mempool.h> @@ -59,12 +61,15 @@ #include <linux/blkdev.h> #include <linux/hdreg.h> +#include <scsi/scsi.h> + #include "i2o_block.h" #define OSM_NAME "block-osm" -#define OSM_VERSION "1.287" +#define OSM_VERSION "1.325" #define OSM_DESCRIPTION "I2O Block Device OSM" +static DEFINE_MUTEX(i2o_block_mutex); static struct i2o_driver i2o_block_driver; /* global Block OSM request mempool */ @@ -130,46 +135,23 @@ static int i2o_block_remove(struct device *dev) */ static int i2o_block_device_flush(struct i2o_device *dev) { - struct i2o_message __iomem *msg; - u32 m; + struct i2o_message *msg; - m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -ETIMEDOUT; + msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); - writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); - writel(I2O_CMD_BLOCK_CFLUSH << 24 | HOST_TID << 12 | dev->lct_data.tid, - &msg->u.head[1]); - writel(60 << 16, &msg->body[0]); + msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_BLOCK_CFLUSH << 24 | HOST_TID << 12 | dev-> + lct_data.tid); + msg->body[0] = cpu_to_le32(60 << 16); osm_debug("Flushing...\n"); - return i2o_msg_post_wait(dev->iop, m, 60); + return i2o_msg_post_wait(dev->iop, msg, 60); }; /** - * i2o_block_issue_flush - device-flush interface for block-layer - * @queue: the request queue of the device which should be flushed - * @disk: gendisk - * @error_sector: error offset - * - * Helper function to provide flush functionality to block-layer. - * - * Returns 0 on success or negative error code on failure. - */ - -static int i2o_block_issue_flush(request_queue_t * queue, struct gendisk *disk, - sector_t * error_sector) -{ - struct i2o_block_device *i2o_blk_dev = queue->queuedata; - int rc = -ENODEV; - - if (likely(i2o_blk_dev)) - rc = i2o_block_device_flush(i2o_blk_dev->i2o_dev); - - return rc; -} - -/** * i2o_block_device_mount - Mount (load) the media of device dev * @dev: I2O device which should receive the mount request * @media_id: Media Identifier @@ -181,21 +163,21 @@ static int i2o_block_issue_flush(request_queue_t * queue, struct gendisk *disk, */ static int i2o_block_device_mount(struct i2o_device *dev, u32 media_id) { - struct i2o_message __iomem *msg; - u32 m; - - m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -ETIMEDOUT; - - writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); - writel(I2O_CMD_BLOCK_MMOUNT << 24 | HOST_TID << 12 | dev->lct_data.tid, - &msg->u.head[1]); - writel(-1, &msg->body[0]); - writel(0, &msg->body[1]); + struct i2o_message *msg; + + msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_BLOCK_MMOUNT << 24 | HOST_TID << 12 | dev-> + lct_data.tid); + msg->body[0] = cpu_to_le32(-1); + msg->body[1] = cpu_to_le32(0x00000000); osm_debug("Mounting...\n"); - return i2o_msg_post_wait(dev->iop, m, 2); + return i2o_msg_post_wait(dev->iop, msg, 2); }; /** @@ -210,20 +192,20 @@ static int i2o_block_device_mount(struct i2o_device *dev, u32 media_id) */ static int i2o_block_device_lock(struct i2o_device *dev, u32 media_id) { - struct i2o_message __iomem *msg; - u32 m; + struct i2o_message *msg; - m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -ETIMEDOUT; + msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); - writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); - writel(I2O_CMD_BLOCK_MLOCK << 24 | HOST_TID << 12 | dev->lct_data.tid, - &msg->u.head[1]); - writel(-1, &msg->body[0]); + msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_BLOCK_MLOCK << 24 | HOST_TID << 12 | dev-> + lct_data.tid); + msg->body[0] = cpu_to_le32(-1); osm_debug("Locking...\n"); - return i2o_msg_post_wait(dev->iop, m, 2); + return i2o_msg_post_wait(dev->iop, msg, 2); }; /** @@ -238,26 +220,26 @@ static int i2o_block_device_lock(struct i2o_device *dev, u32 media_id) */ static int i2o_block_device_unlock(struct i2o_device *dev, u32 media_id) { - struct i2o_message __iomem *msg; - u32 m; + struct i2o_message *msg; - m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -ETIMEDOUT; + msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); - writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); - writel(I2O_CMD_BLOCK_MUNLOCK << 24 | HOST_TID << 12 | dev->lct_data.tid, - &msg->u.head[1]); - writel(media_id, &msg->body[0]); + msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_BLOCK_MUNLOCK << 24 | HOST_TID << 12 | dev-> + lct_data.tid); + msg->body[0] = cpu_to_le32(media_id); osm_debug("Unlocking...\n"); - return i2o_msg_post_wait(dev->iop, m, 2); + return i2o_msg_post_wait(dev->iop, msg, 2); }; /** * i2o_block_device_power - Power management for device dev * @dev: I2O device which should receive the power management request - * @operation: Operation which should be send + * @op: Operation to send * * Send a power management request to the device dev. * @@ -267,21 +249,21 @@ static int i2o_block_device_power(struct i2o_block_device *dev, u8 op) { struct i2o_device *i2o_dev = dev->i2o_dev; struct i2o_controller *c = i2o_dev->iop; - struct i2o_message __iomem *msg; - u32 m; + struct i2o_message *msg; int rc; - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -ETIMEDOUT; + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); - writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); - writel(I2O_CMD_BLOCK_POWER << 24 | HOST_TID << 12 | i2o_dev->lct_data. - tid, &msg->u.head[1]); - writel(op << 24, &msg->body[0]); + msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_BLOCK_POWER << 24 | HOST_TID << 12 | i2o_dev-> + lct_data.tid); + msg->body[0] = cpu_to_le32(op << 24); osm_debug("Power...\n"); - rc = i2o_msg_post_wait(c, m, 60); + rc = i2o_msg_post_wait(c, msg, 60); if (!rc) dev->power = op; @@ -305,6 +287,7 @@ static inline struct i2o_block_request *i2o_block_request_alloc(void) return ERR_PTR(-ENOMEM); INIT_LIST_HEAD(&ireq->queue); + sg_init_table(ireq->sg_table, I2O_MAX_PHYS_SEGMENTS); return ireq; }; @@ -313,7 +296,7 @@ static inline struct i2o_block_request *i2o_block_request_alloc(void) * i2o_block_request_free - Frees a I2O block request * @ireq: I2O block request which should be freed * - * Fres the allocated memory (give it back to the request mempool). + * Frees the allocated memory (give it back to the request mempool). */ static inline void i2o_block_request_free(struct i2o_block_request *ireq) { @@ -324,14 +307,15 @@ static inline void i2o_block_request_free(struct i2o_block_request *ireq) * i2o_block_sglist_alloc - Allocate the SG list and map it * @c: I2O controller to which the request belongs * @ireq: I2O block request + * @mptr: message body pointer * - * Builds the SG list and map it to be accessable by the controller. + * Builds the SG list and map it to be accessible by the controller. * * Returns 0 on failure or 1 on success. */ static inline int i2o_block_sglist_alloc(struct i2o_controller *c, struct i2o_block_request *ireq, - u32 __iomem ** mptr) + u32 ** mptr) { int nents; enum dma_data_direction direction; @@ -373,7 +357,7 @@ static inline void i2o_block_sglist_free(struct i2o_block_request *ireq) * @req: the request to prepare * * Allocate the necessary i2o_block_request struct and connect it to - * the request. This is needed that we not loose the SG list later on. + * the request. This is needed that we not lose the SG list later on. * * Returns BLKPREP_OK on success or BLKPREP_DEFER on failure. */ @@ -387,17 +371,10 @@ static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req) return BLKPREP_KILL; } - /* request is already processed by us, so return */ - if (req->flags & REQ_SPECIAL) { - osm_debug("REQ_SPECIAL already set!\n"); - req->flags |= REQ_DONTPREP; - return BLKPREP_OK; - } - /* connect the i2o_block_request to the request */ if (!req->special) { ireq = i2o_block_request_alloc(); - if (unlikely(IS_ERR(ireq))) { + if (IS_ERR(ireq)) { osm_debug("unable to allocate i2o_block_request!\n"); return BLKPREP_DEFER; } @@ -405,27 +382,27 @@ static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req) ireq->i2o_blk_dev = i2o_blk_dev; req->special = ireq; ireq->req = req; - } else - ireq = req->special; - + } /* do not come back here */ - req->flags |= REQ_DONTPREP | REQ_SPECIAL; + req->cmd_flags |= REQ_DONTPREP; return BLKPREP_OK; }; /** * i2o_block_delayed_request_fn - delayed request queue function - * delayed_request: the delayed request with the queue to start + * @work: the delayed request with the queue to start * * If the request queue is stopped for a disk, and there is no open * request, a new event is created, which calls this function to start * the queue after I2O_BLOCK_REQUEST_TIME. Otherwise the queue will never * be started again. */ -static void i2o_block_delayed_request_fn(void *delayed_request) +static void i2o_block_delayed_request_fn(struct work_struct *work) { - struct i2o_block_delayed_request *dreq = delayed_request; + struct i2o_block_delayed_request *dreq = + container_of(work, struct i2o_block_delayed_request, + work.work); struct request_queue *q = dreq->queue; unsigned long flags; @@ -438,36 +415,26 @@ static void i2o_block_delayed_request_fn(void *delayed_request) /** * i2o_block_end_request - Post-processing of completed commands * @req: request which should be completed - * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error + * @error: 0 for success, < 0 for error * @nr_bytes: number of bytes to complete * * Mark the request as complete. The lock must not be held when entering. * */ -static void i2o_block_end_request(struct request *req, int uptodate, +static void i2o_block_end_request(struct request *req, int error, int nr_bytes) { struct i2o_block_request *ireq = req->special; struct i2o_block_device *dev = ireq->i2o_blk_dev; - request_queue_t *q = req->q; + struct request_queue *q = req->q; unsigned long flags; - if (end_that_request_chunk(req, uptodate, nr_bytes)) { - int leftover = (req->hard_nr_sectors << KERNEL_SECTOR_SHIFT); - - if (blk_pc_request(req)) - leftover = req->data_len; - - if (end_io_error(uptodate)) - end_that_request_chunk(req, 0, leftover); - } - - add_disk_randomness(req->rq_disk); + if (blk_end_request(req, error, nr_bytes)) + if (error) + blk_end_request_all(req, -EIO); spin_lock_irqsave(q->queue_lock, flags); - end_that_request_last(req); - if (likely(dev)) { dev->open_queue_depth--; list_del(&ireq->queue); @@ -485,7 +452,7 @@ static void i2o_block_end_request(struct request *req, int uptodate, * i2o_block_reply - Block OSM reply handler. * @c: I2O controller from which the message arrives * @m: message id of reply - * qmsg: the actuall I2O message reply + * @msg: the actual I2O message reply * * This function gets all the message replies. * @@ -494,7 +461,7 @@ static int i2o_block_reply(struct i2o_controller *c, u32 m, struct i2o_message *msg) { struct request *req; - int uptodate = 1; + int error = 0; req = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt)); if (unlikely(!req)) { @@ -527,16 +494,17 @@ static int i2o_block_reply(struct i2o_controller *c, u32 m, req->errors++; - uptodate = 0; + error = -EIO; } - i2o_block_end_request(req, uptodate, le32_to_cpu(msg->body[1])); + i2o_block_end_request(req, error, le32_to_cpu(msg->body[1])); return 1; }; -static void i2o_block_event(struct i2o_event *evt) +static void i2o_block_event(struct work_struct *work) { + struct i2o_event *evt = container_of(work, struct i2o_event, work); osm_debug("event received\n"); kfree(evt); }; @@ -596,19 +564,22 @@ static void i2o_block_biosparam(unsigned long capacity, unsigned short *cyls, /** * i2o_block_open - Open the block device + * @bdev: block device being opened + * @mode: file open mode * * Power up the device, mount and lock the media. This function is called, * if the block device is opened for access. * * Returns 0 on success or negative error code on failure. */ -static int i2o_block_open(struct inode *inode, struct file *file) +static int i2o_block_open(struct block_device *bdev, fmode_t mode) { - struct i2o_block_device *dev = inode->i_bdev->bd_disk->private_data; + struct i2o_block_device *dev = bdev->bd_disk->private_data; if (!dev->i2o_dev) return -ENODEV; + mutex_lock(&i2o_block_mutex); if (dev->power > 0x1f) i2o_block_device_power(dev, 0x02); @@ -617,35 +588,36 @@ static int i2o_block_open(struct inode *inode, struct file *file) i2o_block_device_lock(dev->i2o_dev, -1); osm_debug("Ready.\n"); + mutex_unlock(&i2o_block_mutex); return 0; }; /** * i2o_block_release - Release the I2O block device + * @disk: gendisk device being released + * @mode: file open mode * * Unlock and unmount the media, and power down the device. Gets called if * the block device is closed. - * - * Returns 0 on success or negative error code on failure. */ -static int i2o_block_release(struct inode *inode, struct file *file) +static void i2o_block_release(struct gendisk *disk, fmode_t mode) { - struct gendisk *disk = inode->i_bdev->bd_disk; struct i2o_block_device *dev = disk->private_data; u8 operation; /* - * This is to deail with the case of an application - * opening a device and then the device dissapears while + * This is to deal with the case of an application + * opening a device and then the device disappears while * it's in use, and then the application tries to release * it. ex: Unmounting a deleted RAID volume at reboot. * If we send messages, it will just cause FAILs since * the TID no longer exists. */ if (!dev->i2o_dev) - return 0; + return; + mutex_lock(&i2o_block_mutex); i2o_block_device_flush(dev->i2o_dev); i2o_block_device_unlock(dev->i2o_dev, -1); @@ -656,12 +628,20 @@ static int i2o_block_release(struct inode *inode, struct file *file) operation = 0x24; i2o_block_device_power(dev, operation); + mutex_unlock(&i2o_block_mutex); +} +static int i2o_block_getgeo(struct block_device *bdev, struct hd_geometry *geo) +{ + i2o_block_biosparam(get_capacity(bdev->bd_disk), + &geo->cylinders, &geo->heads, &geo->sectors); return 0; } /** * i2o_block_ioctl - Issue device specific ioctl calls. + * @bdev: block device being opened + * @mode: file open mode * @cmd: ioctl command * @arg: arg * @@ -669,69 +649,71 @@ static int i2o_block_release(struct inode *inode, struct file *file) * * Return 0 on success or negative error on failure. */ -static int i2o_block_ioctl(struct inode *inode, struct file *file, +static int i2o_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { - struct gendisk *disk = inode->i_bdev->bd_disk; + struct gendisk *disk = bdev->bd_disk; struct i2o_block_device *dev = disk->private_data; - void __user *argp = (void __user *)arg; + int ret = -ENOTTY; /* Anyone capable of this syscall can do *real bad* things */ if (!capable(CAP_SYS_ADMIN)) return -EPERM; + mutex_lock(&i2o_block_mutex); switch (cmd) { - case HDIO_GETGEO: - { - struct hd_geometry g; - i2o_block_biosparam(get_capacity(disk), - &g.cylinders, &g.heads, &g.sectors); - g.start = get_start_sect(inode->i_bdev); - return copy_to_user(argp, &g, sizeof(g)) ? -EFAULT : 0; - } - case BLKI2OGRSTRAT: - return put_user(dev->rcache, (int __user *)arg); + ret = put_user(dev->rcache, (int __user *)arg); + break; case BLKI2OGWSTRAT: - return put_user(dev->wcache, (int __user *)arg); + ret = put_user(dev->wcache, (int __user *)arg); + break; case BLKI2OSRSTRAT: + ret = -EINVAL; if (arg < 0 || arg > CACHE_SMARTFETCH) - return -EINVAL; + break; dev->rcache = arg; + ret = 0; break; case BLKI2OSWSTRAT: + ret = -EINVAL; if (arg != 0 && (arg < CACHE_WRITETHROUGH || arg > CACHE_SMARTBACK)) - return -EINVAL; + break; dev->wcache = arg; + ret = 0; break; } - return -ENOTTY; + mutex_unlock(&i2o_block_mutex); + + return ret; }; /** - * i2o_block_media_changed - Have we seen a media change? + * i2o_block_check_events - Have we seen a media change? * @disk: gendisk which should be verified + * @clearing: events being cleared * * Verifies if the media has changed. * * Returns 1 if the media was changed or 0 otherwise. */ -static int i2o_block_media_changed(struct gendisk *disk) +static unsigned int i2o_block_check_events(struct gendisk *disk, + unsigned int clearing) { struct i2o_block_device *p = disk->private_data; if (p->media_change_flag) { p->media_change_flag = 0; - return 1; + return DISK_EVENT_MEDIA_CHANGE; } return 0; } /** * i2o_block_transfer - Transfer a request to/from the I2O controller - * @req: the request which should be transfered + * @req: the request which should be transferred * * This function converts the request into a I2O message. The necessary * DMA buffers are allocated and after everything is setup post the message @@ -744,11 +726,10 @@ static int i2o_block_transfer(struct request *req) { struct i2o_block_device *dev = req->rq_disk->private_data; struct i2o_controller *c; - int tid = dev->i2o_dev->lct_data.tid; - struct i2o_message __iomem *msg; - u32 __iomem *mptr; + u32 tid; + struct i2o_message *msg; + u32 *mptr; struct i2o_block_request *ireq = req->special; - u32 m; u32 tcntxt; u32 sgl_offset = SGL_OFFSET_8; u32 ctl_flags = 0x00000000; @@ -761,11 +742,12 @@ static int i2o_block_transfer(struct request *req) goto exit; } + tid = dev->i2o_dev->lct_data.tid; c = dev->i2o_dev->iop; - m = i2o_msg_get(c, &msg); - if (m == I2O_QUEUE_EMPTY) { - rc = -EBUSY; + msg = i2o_msg_get(c); + if (IS_ERR(msg)) { + rc = PTR_ERR(msg); goto exit; } @@ -775,8 +757,8 @@ static int i2o_block_transfer(struct request *req) goto nop_msg; } - writel(i2o_block_driver.context, &msg->u.s.icntxt); - writel(tcntxt, &msg->u.s.tcntxt); + msg->u.s.icntxt = cpu_to_le32(i2o_block_driver.context); + msg->u.s.tcntxt = cpu_to_le32(tcntxt); mptr = &msg->body[0]; @@ -789,7 +771,7 @@ static int i2o_block_transfer(struct request *req) break; case CACHE_SMARTFETCH: - if (req->nr_sectors > 16) + if (blk_rq_sectors(req) > 16) ctl_flags = 0x201F0008; else ctl_flags = 0x001F0000; @@ -809,13 +791,13 @@ static int i2o_block_transfer(struct request *req) ctl_flags = 0x001F0010; break; case CACHE_SMARTBACK: - if (req->nr_sectors > 16) + if (blk_rq_sectors(req) > 16) ctl_flags = 0x001F0004; else ctl_flags = 0x001F0010; break; case CACHE_SMARTTHROUGH: - if (req->nr_sectors > 16) + if (blk_rq_sectors(req) > 16) ctl_flags = 0x001F0004; else ctl_flags = 0x001F0010; @@ -828,17 +810,18 @@ static int i2o_block_transfer(struct request *req) if (c->adaptec) { u8 cmd[10]; u32 scsi_flags; - u16 hwsec = queue_hardsect_size(req->q) >> KERNEL_SECTOR_SHIFT; + u16 hwsec; + hwsec = queue_logical_block_size(req->q) >> KERNEL_SECTOR_SHIFT; memset(cmd, 0, 10); sgl_offset = SGL_OFFSET_12; - writel(I2O_CMD_PRIVATE << 24 | HOST_TID << 12 | tid, - &msg->u.head[1]); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_PRIVATE << 24 | HOST_TID << 12 | tid); - writel(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC, mptr++); - writel(tid, mptr++); + *mptr++ = cpu_to_le32(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC); + *mptr++ = cpu_to_le32(tid); /* * ENABLE_DISCONNECT @@ -846,29 +829,31 @@ static int i2o_block_transfer(struct request *req) * RETURN_SENSE_DATA_IN_REPLY_MESSAGE_FRAME */ if (rq_data_dir(req) == READ) { - cmd[0] = 0x28; + cmd[0] = READ_10; scsi_flags = 0x60a0000a; } else { - cmd[0] = 0x2A; + cmd[0] = WRITE_10; scsi_flags = 0xa0a0000a; } - writel(scsi_flags, mptr++); + *mptr++ = cpu_to_le32(scsi_flags); - *((u32 *) & cmd[2]) = cpu_to_be32(req->sector * hwsec); - *((u16 *) & cmd[7]) = cpu_to_be16(req->nr_sectors * hwsec); + *((u32 *) & cmd[2]) = cpu_to_be32(blk_rq_pos(req) * hwsec); + *((u16 *) & cmd[7]) = cpu_to_be16(blk_rq_sectors(req) * hwsec); - memcpy_toio(mptr, cmd, 10); + memcpy(mptr, cmd, 10); mptr += 4; - writel(req->nr_sectors << KERNEL_SECTOR_SHIFT, mptr++); + *mptr++ = cpu_to_le32(blk_rq_bytes(req)); } else #endif { - writel(cmd | HOST_TID << 12 | tid, &msg->u.head[1]); - writel(ctl_flags, mptr++); - writel(req->nr_sectors << KERNEL_SECTOR_SHIFT, mptr++); - writel((u32) (req->sector << KERNEL_SECTOR_SHIFT), mptr++); - writel(req->sector >> (32 - KERNEL_SECTOR_SHIFT), mptr++); + msg->u.head[1] = cpu_to_le32(cmd | HOST_TID << 12 | tid); + *mptr++ = cpu_to_le32(ctl_flags); + *mptr++ = cpu_to_le32(blk_rq_bytes(req)); + *mptr++ = + cpu_to_le32((u32) (blk_rq_pos(req) << KERNEL_SECTOR_SHIFT)); + *mptr++ = + cpu_to_le32(blk_rq_pos(req) >> (32 - KERNEL_SECTOR_SHIFT)); } if (!i2o_block_sglist_alloc(c, ireq, &mptr)) { @@ -876,13 +861,13 @@ static int i2o_block_transfer(struct request *req) goto context_remove; } - writel(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | - sgl_offset, &msg->u.head[0]); + msg->u.head[0] = + cpu_to_le32(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset); list_add_tail(&ireq->queue, &dev->open_queue); dev->open_queue_depth++; - i2o_msg_post(c, m); + i2o_msg_post(c, msg); return 0; @@ -890,7 +875,7 @@ static int i2o_block_transfer(struct request *req) i2o_cntxt_list_remove(c, req); nop_msg: - i2o_msg_nop(c, m); + i2o_msg_nop(c, msg); exit: return rc; @@ -898,7 +883,7 @@ static int i2o_block_transfer(struct request *req) /** * i2o_block_request_fn - request queue handling function - * q: request queue from which the request could be fetched + * @q: request queue from which the request could be fetched * * Takes the next request from the queue, transfers it and if no error * occurs dequeue it from the queue. On arrival of the reply the message @@ -908,12 +893,8 @@ static void i2o_block_request_fn(struct request_queue *q) { struct request *req; - while (!blk_queue_plugged(q)) { - req = elv_next_request(q); - if (!req) - break; - - if (blk_fs_request(req)) { + while ((req = blk_peek_request(q)) != NULL) { + if (req->cmd_type == REQ_TYPE_FS) { struct i2o_block_delayed_request *dreq; struct i2o_block_request *ireq = req->special; unsigned int queue_depth; @@ -922,7 +903,7 @@ static void i2o_block_request_fn(struct request_queue *q) if (queue_depth < I2O_BLOCK_MAX_OPEN_REQUESTS) { if (!i2o_block_transfer(req)) { - blkdev_dequeue_request(req); + blk_start_request(req); continue; } else osm_info("transfer error\n"); @@ -937,8 +918,8 @@ static void i2o_block_request_fn(struct request_queue *q) continue; dreq->queue = q; - INIT_WORK(&dreq->work, i2o_block_delayed_request_fn, - dreq); + INIT_DELAYED_WORK(&dreq->work, + i2o_block_delayed_request_fn); if (!queue_delayed_work(i2o_block_driver.event_queue, &dreq->work, @@ -948,18 +929,22 @@ static void i2o_block_request_fn(struct request_queue *q) blk_stop_queue(q); break; } - } else - end_request(req, 0); + } else { + blk_start_request(req); + __blk_end_request_all(req, -EIO); + } } }; /* I2O Block device operations definition */ -static struct block_device_operations i2o_block_fops = { +static const struct block_device_operations i2o_block_fops = { .owner = THIS_MODULE, .open = i2o_block_open, .release = i2o_block_release, .ioctl = i2o_block_ioctl, - .media_changed = i2o_block_media_changed + .compat_ioctl = i2o_block_ioctl, + .getgeo = i2o_block_getgeo, + .check_events = i2o_block_check_events, }; /** @@ -968,7 +953,7 @@ static struct block_device_operations i2o_block_fops = { * Allocate memory for the i2o_block_device struct, gendisk and request * queue and initialize them as far as no additional information is needed. * - * Returns a pointer to the allocated I2O Block device on succes or a + * Returns a pointer to the allocated I2O Block device on success or a * negative error code on failure. */ static struct i2o_block_device *i2o_block_device_alloc(void) @@ -978,13 +963,12 @@ static struct i2o_block_device *i2o_block_device_alloc(void) struct request_queue *queue; int rc; - dev = kmalloc(sizeof(*dev), GFP_KERNEL); + dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) { osm_err("Insufficient memory to allocate I2O Block disk.\n"); rc = -ENOMEM; goto exit; } - memset(dev, 0, sizeof(*dev)); INIT_LIST_HEAD(&dev->open_queue); spin_lock_init(&dev->lock); @@ -1008,7 +992,6 @@ static struct i2o_block_device *i2o_block_device_alloc(void) } blk_queue_prep_rq(queue, i2o_block_prep_req_fn); - blk_queue_issue_flush_fn(queue, i2o_block_issue_flush); gd->major = I2O_MAJOR; gd->queue = queue; @@ -1049,8 +1032,8 @@ static int i2o_block_probe(struct device *dev) int rc; u64 size; u32 blocksize; - u32 flags, status; u16 body_size = 4; + u16 power; unsigned short max_sectors; #ifdef CONFIG_I2O_EXT_ADAPTEC @@ -1089,41 +1072,37 @@ static int i2o_block_probe(struct device *dev) gd = i2o_blk_dev->gd; gd->first_minor = unit << 4; sprintf(gd->disk_name, "i2o/hd%c", 'a' + unit); - sprintf(gd->devfs_name, "i2o/hd%c", 'a' + unit); gd->driverfs_dev = &i2o_dev->device; /* setup request queue */ queue = gd->queue; queue->queuedata = i2o_blk_dev; - blk_queue_max_phys_segments(queue, I2O_MAX_PHYS_SEGMENTS); - blk_queue_max_sectors(queue, max_sectors); - blk_queue_max_hw_segments(queue, i2o_sg_tablesize(c, body_size)); + blk_queue_max_hw_sectors(queue, max_sectors); + blk_queue_max_segments(queue, i2o_sg_tablesize(c, body_size)); - osm_debug("max sectors = %d\n", queue->max_phys_segments); - osm_debug("phys segments = %d\n", queue->max_sectors); + osm_debug("max sectors = %d\n", queue->max_sectors); + osm_debug("phys segments = %d\n", queue->max_phys_segments); osm_debug("max hw segments = %d\n", queue->max_hw_segments); /* * Ask for the current media data. If that isn't supported * then we ask for the device capacity data */ - if (i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) || - i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4)) { - blk_queue_hardsect_size(queue, blocksize); + if (!i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) || + !i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4)) { + blk_queue_logical_block_size(queue, le32_to_cpu(blocksize)); } else osm_warn("unable to get blocksize of %s\n", gd->disk_name); - if (i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) || - i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8)) { - set_capacity(gd, size >> KERNEL_SECTOR_SHIFT); + if (!i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) || + !i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8)) { + set_capacity(gd, le64_to_cpu(size) >> KERNEL_SECTOR_SHIFT); } else osm_warn("could not get size of %s\n", gd->disk_name); - if (!i2o_parm_field_get(i2o_dev, 0x0000, 2, &i2o_blk_dev->power, 2)) - i2o_blk_dev->power = 0; - i2o_parm_field_get(i2o_dev, 0x0000, 5, &flags, 4); - i2o_parm_field_get(i2o_dev, 0x0000, 6, &status, 4); + if (!i2o_parm_field_get(i2o_dev, 0x0000, 2, &power, 2)) + i2o_blk_dev->power = power; i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0xffffffff); @@ -1173,18 +1152,16 @@ static int __init i2o_block_init(void) /* Allocate request mempool and slab */ size = sizeof(struct i2o_block_request); i2o_blk_req_pool.slab = kmem_cache_create("i2o_block_req", size, 0, - SLAB_HWCACHE_ALIGN, NULL, - NULL); + SLAB_HWCACHE_ALIGN, NULL); if (!i2o_blk_req_pool.slab) { osm_err("can't init request slab\n"); rc = -ENOMEM; goto exit; } - i2o_blk_req_pool.pool = mempool_create(I2O_BLOCK_REQ_MEMPOOL_SIZE, - mempool_alloc_slab, - mempool_free_slab, - i2o_blk_req_pool.slab); + i2o_blk_req_pool.pool = + mempool_create_slab_pool(I2O_BLOCK_REQ_MEMPOOL_SIZE, + i2o_blk_req_pool.slab); if (!i2o_blk_req_pool.pool) { osm_err("can't init request mempool\n"); rc = -ENOMEM; diff --git a/drivers/message/i2o/i2o_block.h b/drivers/message/i2o/i2o_block.h index 4fdaa5bda41..cf8873cbca3 100644 --- a/drivers/message/i2o/i2o_block.h +++ b/drivers/message/i2o/i2o_block.h @@ -64,7 +64,7 @@ /* I2O Block OSM mempool struct */ struct i2o_block_mempool { - kmem_cache_t *slab; + struct kmem_cache *slab; mempool_t *pool; }; @@ -73,7 +73,7 @@ struct i2o_block_device { struct i2o_device *i2o_dev; /* pointer to I2O device */ struct gendisk *gd; spinlock_t lock; /* queue lock */ - struct list_head open_queue; /* list of transfered, but unfinished + struct list_head open_queue; /* list of transferred, but unfinished requests */ unsigned int open_queue_depth; /* number of requests in the queue */ @@ -96,7 +96,7 @@ struct i2o_block_request { /* I2O Block device delayed request */ struct i2o_block_delayed_request { - struct work_struct work; + struct delayed_work work; struct request_queue *queue; }; diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c index 3c3a7abebb1..04bd3b6de40 100644 --- a/drivers/message/i2o/i2o_config.c +++ b/drivers/message/i2o/i2o_config.c @@ -10,16 +10,16 @@ * Added basic ioctl() support * Deepak Saxena (06/07/1999): * Added software download ioctl (still testing) - * Auvo Häkkinen (09/10/1999): + * Auvo Häkkinen (09/10/1999): * Changes to i2o_cfg_reply(), ioctl_parms() * Added ioct_validate() - * Taneli Vähäkangas (09/30/1999): + * Taneli Vähäkangas (09/30/1999): * Fixed ioctl_swdl() - * Taneli Vähäkangas (10/04/1999): + * Taneli Vähäkangas (10/04/1999): * Changed ioctl_swdl(), implemented ioctl_swul() and ioctl_swdel() * Deepak Saxena (11/18/1999): * Added event managmenet support - * Alan Cox <alan@redhat.com>: + * Alan Cox <alan@lxorguk.ukuu.org.uk>: * 2.4 rewrite ported to 2.5 * Markus Lidel <Markus.Lidel@shadowconnect.com>: * Added pass-thru support for Adaptec's raidutils @@ -31,8 +31,9 @@ */ #include <linux/miscdevice.h> -#include <linux/smp_lock.h> +#include <linux/mutex.h> #include <linux/compat.h> +#include <linux/slab.h> #include <asm/uaccess.h> @@ -40,8 +41,8 @@ #define SG_TABLESIZE 30 -static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd, - unsigned long arg); +static DEFINE_MUTEX(i2o_cfg_mutex); +static long i2o_cfg_ioctl(struct file *, unsigned int, unsigned long); static spinlock_t i2o_config_lock; @@ -111,11 +112,11 @@ static int i2o_cfg_gethrt(unsigned long arg) len = 8 + ((hrt->entry_len * hrt->num_entries) << 2); - /* We did a get user...so assuming mem is ok...is this bad? */ - put_user(len, kcmd.reslen); - if (len > reslen) + if (put_user(len, kcmd.reslen)) + ret = -EFAULT; + else if (len > reslen) ret = -ENOBUFS; - if (copy_to_user(kcmd.resbuf, (void *)hrt, len)) + else if (copy_to_user(kcmd.resbuf, (void *)hrt, len)) ret = -EFAULT; return ret; @@ -147,8 +148,9 @@ static int i2o_cfg_getlct(unsigned long arg) lct = (i2o_lct *) c->lct; len = (unsigned int)lct->table_size << 2; - put_user(len, kcmd.reslen); - if (len > reslen) + if (put_user(len, kcmd.reslen)) + ret = -EFAULT; + else if (len > reslen) ret = -ENOBUFS; else if (copy_to_user(kcmd.resbuf, lct, len)) ret = -EFAULT; @@ -186,20 +188,22 @@ static int i2o_cfg_parms(unsigned long arg, unsigned int type) if (!dev) return -ENXIO; - ops = (u8 *) kmalloc(kcmd.oplen, GFP_KERNEL); - if (!ops) - return -ENOMEM; + /* + * Stop users being able to try and allocate arbitrary amounts + * of DMA space. 64K is way more than sufficient for this. + */ + if (kcmd.oplen > 65536) + return -EMSGSIZE; - if (copy_from_user(ops, kcmd.opbuf, kcmd.oplen)) { - kfree(ops); - return -EFAULT; - } + ops = memdup_user(kcmd.opbuf, kcmd.oplen); + if (IS_ERR(ops)) + return PTR_ERR(ops); /* * It's possible to have a _very_ large table * and that the user asks for all of it at once... */ - res = (u8 *) kmalloc(65536, GFP_KERNEL); + res = kmalloc(65536, GFP_KERNEL); if (!res) { kfree(ops); return -ENOMEM; @@ -213,8 +217,9 @@ static int i2o_cfg_parms(unsigned long arg, unsigned int type) return -EAGAIN; } - put_user(len, kcmd.reslen); - if (len > reslen) + if (put_user(len, kcmd.reslen)) + ret = -EFAULT; + else if (len > reslen) ret = -ENOBUFS; else if (copy_to_user(kcmd.resbuf, res, len)) ret = -EFAULT; @@ -230,8 +235,7 @@ static int i2o_cfg_swdl(unsigned long arg) struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg; unsigned char maxfrag = 0, curfrag = 1; struct i2o_dma buffer; - struct i2o_message __iomem *msg; - u32 m; + struct i2o_message *msg; unsigned int status = 0, swlen = 0, fragsize = 8192; struct i2o_controller *c; @@ -257,31 +261,38 @@ static int i2o_cfg_swdl(unsigned long arg) if (!c) return -ENXIO; - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -EBUSY; + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); - if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize, GFP_KERNEL)) { - i2o_msg_nop(c, m); + if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize)) { + i2o_msg_nop(c, msg); return -ENOMEM; } - __copy_from_user(buffer.virt, kxfer.buf, fragsize); + if (__copy_from_user(buffer.virt, kxfer.buf, fragsize)) { + i2o_msg_nop(c, msg); + i2o_dma_free(&c->pdev->dev, &buffer); + return -EFAULT; + } - writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]); - writel(I2O_CMD_SW_DOWNLOAD << 24 | HOST_TID << 12 | ADAPTER_TID, - &msg->u.head[1]); - writel(i2o_config_driver.context, &msg->u.head[2]); - writel(0, &msg->u.head[3]); - writel((((u32) kxfer.flags) << 24) | (((u32) kxfer.sw_type) << 16) | - (((u32) maxfrag) << 8) | (((u32) curfrag)), &msg->body[0]); - writel(swlen, &msg->body[1]); - writel(kxfer.sw_id, &msg->body[2]); - writel(0xD0000000 | fragsize, &msg->body[3]); - writel(buffer.phys, &msg->body[4]); + msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_7); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_SW_DOWNLOAD << 24 | HOST_TID << 12 | + ADAPTER_TID); + msg->u.head[2] = cpu_to_le32(i2o_config_driver.context); + msg->u.head[3] = cpu_to_le32(0); + msg->body[0] = + cpu_to_le32((((u32) kxfer.flags) << 24) | (((u32) kxfer. + sw_type) << 16) | + (((u32) maxfrag) << 8) | (((u32) curfrag))); + msg->body[1] = cpu_to_le32(swlen); + msg->body[2] = cpu_to_le32(kxfer.sw_id); + msg->body[3] = cpu_to_le32(0xD0000000 | fragsize); + msg->body[4] = cpu_to_le32(buffer.phys); osm_debug("swdl frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize); - status = i2o_msg_post_wait_mem(c, m, 60, &buffer); + status = i2o_msg_post_wait_mem(c, msg, 60, &buffer); if (status != -ETIMEDOUT) i2o_dma_free(&c->pdev->dev, &buffer); @@ -302,58 +313,57 @@ static int i2o_cfg_swul(unsigned long arg) struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg; unsigned char maxfrag = 0, curfrag = 1; struct i2o_dma buffer; - struct i2o_message __iomem *msg; - u32 m; + struct i2o_message *msg; unsigned int status = 0, swlen = 0, fragsize = 8192; struct i2o_controller *c; int ret = 0; if (copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer))) - goto return_fault; + return -EFAULT; if (get_user(swlen, kxfer.swlen) < 0) - goto return_fault; + return -EFAULT; if (get_user(maxfrag, kxfer.maxfrag) < 0) - goto return_fault; + return -EFAULT; if (get_user(curfrag, kxfer.curfrag) < 0) - goto return_fault; + return -EFAULT; if (curfrag == maxfrag) fragsize = swlen - (maxfrag - 1) * 8192; if (!kxfer.buf) - goto return_fault; + return -EFAULT; c = i2o_find_iop(kxfer.iop); if (!c) return -ENXIO; - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -EBUSY; + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); - if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize, GFP_KERNEL)) { - i2o_msg_nop(c, m); + if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize)) { + i2o_msg_nop(c, msg); return -ENOMEM; } - writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]); - writel(I2O_CMD_SW_UPLOAD << 24 | HOST_TID << 12 | ADAPTER_TID, - &msg->u.head[1]); - writel(i2o_config_driver.context, &msg->u.head[2]); - writel(0, &msg->u.head[3]); - writel((u32) kxfer.flags << 24 | (u32) kxfer. - sw_type << 16 | (u32) maxfrag << 8 | (u32) curfrag, - &msg->body[0]); - writel(swlen, &msg->body[1]); - writel(kxfer.sw_id, &msg->body[2]); - writel(0xD0000000 | fragsize, &msg->body[3]); - writel(buffer.phys, &msg->body[4]); + msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_7); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_SW_UPLOAD << 24 | HOST_TID << 12 | ADAPTER_TID); + msg->u.head[2] = cpu_to_le32(i2o_config_driver.context); + msg->u.head[3] = cpu_to_le32(0); + msg->body[0] = + cpu_to_le32((u32) kxfer.flags << 24 | (u32) kxfer. + sw_type << 16 | (u32) maxfrag << 8 | (u32) curfrag); + msg->body[1] = cpu_to_le32(swlen); + msg->body[2] = cpu_to_le32(kxfer.sw_id); + msg->body[3] = cpu_to_le32(0xD0000000 | fragsize); + msg->body[4] = cpu_to_le32(buffer.phys); osm_debug("swul frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize); - status = i2o_msg_post_wait_mem(c, m, 60, &buffer); + status = i2o_msg_post_wait_mem(c, msg, 60, &buffer); if (status != I2O_POST_WAIT_OK) { if (status != -ETIMEDOUT) @@ -368,20 +378,15 @@ static int i2o_cfg_swul(unsigned long arg) i2o_dma_free(&c->pdev->dev, &buffer); - return_ret: return ret; - return_fault: - ret = -EFAULT; - goto return_ret; -}; +} static int i2o_cfg_swdel(unsigned long arg) { struct i2o_controller *c; struct i2o_sw_xfer kxfer; struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg; - struct i2o_message __iomem *msg; - u32 m; + struct i2o_message *msg; unsigned int swlen; int token; @@ -395,21 +400,21 @@ static int i2o_cfg_swdel(unsigned long arg) if (!c) return -ENXIO; - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -EBUSY; + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); - writel(SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); - writel(I2O_CMD_SW_REMOVE << 24 | HOST_TID << 12 | ADAPTER_TID, - &msg->u.head[1]); - writel(i2o_config_driver.context, &msg->u.head[2]); - writel(0, &msg->u.head[3]); - writel((u32) kxfer.flags << 24 | (u32) kxfer.sw_type << 16, - &msg->body[0]); - writel(swlen, &msg->body[1]); - writel(kxfer.sw_id, &msg->body[2]); + msg->u.head[0] = cpu_to_le32(SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_SW_REMOVE << 24 | HOST_TID << 12 | ADAPTER_TID); + msg->u.head[2] = cpu_to_le32(i2o_config_driver.context); + msg->u.head[3] = cpu_to_le32(0); + msg->body[0] = + cpu_to_le32((u32) kxfer.flags << 24 | (u32) kxfer.sw_type << 16); + msg->body[1] = cpu_to_le32(swlen); + msg->body[2] = cpu_to_le32(kxfer.sw_id); - token = i2o_msg_post_wait(c, m, 10); + token = i2o_msg_post_wait(c, msg, 10); if (token != I2O_POST_WAIT_OK) { osm_info("swdel failed, DetailedStatus = %d\n", token); @@ -423,25 +428,24 @@ static int i2o_cfg_validate(unsigned long arg) { int token; int iop = (int)arg; - struct i2o_message __iomem *msg; - u32 m; + struct i2o_message *msg; struct i2o_controller *c; c = i2o_find_iop(iop); if (!c) return -ENXIO; - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -EBUSY; + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); - writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); - writel(I2O_CMD_CONFIG_VALIDATE << 24 | HOST_TID << 12 | iop, - &msg->u.head[1]); - writel(i2o_config_driver.context, &msg->u.head[2]); - writel(0, &msg->u.head[3]); + msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_CONFIG_VALIDATE << 24 | HOST_TID << 12 | iop); + msg->u.head[2] = cpu_to_le32(i2o_config_driver.context); + msg->u.head[3] = cpu_to_le32(0); - token = i2o_msg_post_wait(c, m, 10); + token = i2o_msg_post_wait(c, msg, 10); if (token != I2O_POST_WAIT_OK) { osm_info("Can't validate configuration, ErrorStatus = %d\n", @@ -454,8 +458,7 @@ static int i2o_cfg_validate(unsigned long arg) static int i2o_cfg_evt_reg(unsigned long arg, struct file *fp) { - struct i2o_message __iomem *msg; - u32 m; + struct i2o_message *msg; struct i2o_evt_id __user *pdesc = (struct i2o_evt_id __user *)arg; struct i2o_evt_id kdesc; struct i2o_controller *c; @@ -474,18 +477,19 @@ static int i2o_cfg_evt_reg(unsigned long arg, struct file *fp) if (!d) return -ENODEV; - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -EBUSY; + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); - writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); - writel(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | kdesc.tid, - &msg->u.head[1]); - writel(i2o_config_driver.context, &msg->u.head[2]); - writel(i2o_cntxt_list_add(c, fp->private_data), &msg->u.head[3]); - writel(kdesc.evt_mask, &msg->body[0]); + msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | + kdesc.tid); + msg->u.head[2] = cpu_to_le32(i2o_config_driver.context); + msg->u.head[3] = cpu_to_le32(i2o_cntxt_list_add(c, fp->private_data)); + msg->body[0] = cpu_to_le32(kdesc.evt_mask); - i2o_msg_post(c, m); + i2o_msg_post(c, msg); return 0; } @@ -517,7 +521,6 @@ static int i2o_cfg_evt_get(unsigned long arg, struct file *fp) return 0; } -#ifdef CONFIG_I2O_EXT_ADAPTEC #ifdef CONFIG_COMPAT static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long arg) @@ -537,7 +540,6 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, u32 sg_index = 0; i2o_status_block *sb; struct i2o_message *msg; - u32 m; unsigned int iop; cmd = (struct i2o_cmd_passthru32 __user *)arg; @@ -553,8 +555,6 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, return -ENXIO; } - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); - sb = c->status_block.virt; if (get_user(size, &user_msg[0])) { @@ -572,32 +572,34 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, size <<= 2; // Convert to bytes + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + rcode = -EFAULT; /* Copy in the user's I2O command */ if (copy_from_user(msg, user_msg, size)) { osm_warn("unable to copy user message\n"); - return -EFAULT; + goto out; } i2o_dump_message(msg); if (get_user(reply_size, &user_reply[0]) < 0) - return -EFAULT; + goto out; reply_size >>= 16; reply_size <<= 2; - reply = kmalloc(reply_size, GFP_KERNEL); + rcode = -ENOMEM; + reply = kzalloc(reply_size, GFP_KERNEL); if (!reply) { printk(KERN_WARNING "%s: Could not allocate reply buffer\n", c->name); - return -ENOMEM; + goto out; } - memset(reply, 0, reply_size); sg_offset = (msg->u.head[0] >> 4) & 0x0f; - writel(i2o_config_driver.context, &msg->u.s.icntxt); - writel(i2o_cntxt_list_add(c, reply), &msg->u.s.tcntxt); - memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE); if (sg_offset) { struct sg_simple_element *sg; @@ -631,17 +633,16 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, goto cleanup; } sg_size = sg[i].flag_count & 0xffffff; - p = &(sg_list[sg_index++]); + p = &(sg_list[sg_index]); /* Allocate memory for the transfer */ - if (i2o_dma_alloc - (&c->pdev->dev, p, sg_size, - PCI_DMA_BIDIRECTIONAL)) { + if (i2o_dma_alloc(&c->pdev->dev, p, sg_size)) { printk(KERN_DEBUG "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", c->name, sg_size, i, sg_count); rcode = -ENOMEM; goto sg_list_cleanup; } + sg_index++; /* Copy in the user's SG buffer if necessary */ if (sg[i]. flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) { @@ -662,12 +663,15 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, } } - rcode = i2o_msg_post_wait(c, m, 60); - if (rcode) + rcode = i2o_msg_post_wait(c, msg, 60); + msg = NULL; + if (rcode) { + reply[4] = ((u32) rcode) << 24; goto sg_list_cleanup; + } if (sg_offset) { - u32 msg[I2O_OUTBOUND_MSG_FRAME_SIZE]; + u32 rmsg[I2O_OUTBOUND_MSG_FRAME_SIZE]; /* Copy back the Scatter Gather buffers back to user space */ u32 j; // TODO 64bit fix @@ -675,7 +679,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, int sg_size; // re-acquire the original message to handle correctly the sg copy operation - memset(&msg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4); + memset(&rmsg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4); // get user msg size in u32s if (get_user(size, &user_msg[0])) { rcode = -EFAULT; @@ -683,8 +687,13 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, } size = size >> 16; size *= 4; + if (size > sizeof(rmsg)) { + rcode = -EINVAL; + goto sg_list_cleanup; + } + /* Copy in the user's I2O command */ - if (copy_from_user(msg, user_msg, size)) { + if (copy_from_user(rmsg, user_msg, size)) { rcode = -EFAULT; goto sg_list_cleanup; } @@ -692,7 +701,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, (size - sg_offset * 4) / sizeof(struct sg_simple_element); // TODO 64bit fix - sg = (struct sg_simple_element *)(msg + sg_offset); + sg = (struct sg_simple_element *)(rmsg + sg_offset); for (j = 0; j < sg_count; j++) { /* Copy out the SG list to user's buffer if necessary */ if (! @@ -714,6 +723,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, } } +sg_list_cleanup: /* Copy back the reply to user space */ if (reply_size) { // we wrote our own values for context - now restore the user supplied ones @@ -722,7 +732,6 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, "%s: Could not copy message context FROM user\n", c->name); rcode = -EFAULT; - goto sg_list_cleanup; } if (copy_to_user(user_reply, reply, reply_size)) { printk(KERN_WARNING @@ -730,13 +739,14 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, rcode = -EFAULT; } } - - sg_list_cleanup: for (i = 0; i < sg_index; i++) i2o_dma_free(&c->pdev->dev, &sg_list[i]); - cleanup: +cleanup: kfree(reply); +out: + if (msg) + i2o_msg_nop(c, msg); return rcode; } @@ -744,24 +754,25 @@ static long i2o_cfg_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg) { int ret; - lock_kernel(); switch (cmd) { case I2OGETIOPS: - ret = i2o_cfg_ioctl(NULL, file, cmd, arg); + ret = i2o_cfg_ioctl(file, cmd, arg); break; case I2OPASSTHRU32: + mutex_lock(&i2o_cfg_mutex); ret = i2o_cfg_passthru32(file, cmd, arg); + mutex_unlock(&i2o_cfg_mutex); break; default: ret = -ENOIOCTLCMD; break; } - unlock_kernel(); return ret; } #endif +#ifdef CONFIG_I2O_EXT_ADAPTEC static int i2o_cfg_passthru(unsigned long arg) { struct i2o_cmd_passthru __user *cmd = @@ -773,15 +784,13 @@ static int i2o_cfg_passthru(unsigned long arg) u32 size = 0; u32 reply_size = 0; u32 rcode = 0; - void *sg_list[SG_TABLESIZE]; + struct i2o_dma sg_list[SG_TABLESIZE]; u32 sg_offset = 0; u32 sg_count = 0; int sg_index = 0; u32 i = 0; - void *p = NULL; i2o_status_block *sb; - struct i2o_message __iomem *msg; - u32 m; + struct i2o_message *msg; unsigned int iop; if (get_user(iop, &cmd->iop) || get_user(user_msg, &cmd->msg)) @@ -793,8 +802,6 @@ static int i2o_cfg_passthru(unsigned long arg) return -ENXIO; } - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); - sb = c->status_block.virt; if (get_user(size, &user_msg[0])) @@ -810,32 +817,35 @@ static int i2o_cfg_passthru(unsigned long arg) size <<= 2; // Convert to bytes + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + rcode = -EFAULT; /* Copy in the user's I2O command */ if (copy_from_user(msg, user_msg, size)) - return -EFAULT; + goto out; if (get_user(reply_size, &user_reply[0]) < 0) - return -EFAULT; + goto out; reply_size >>= 16; reply_size <<= 2; - reply = kmalloc(reply_size, GFP_KERNEL); + reply = kzalloc(reply_size, GFP_KERNEL); if (!reply) { printk(KERN_WARNING "%s: Could not allocate reply buffer\n", c->name); - return -ENOMEM; + rcode = -ENOMEM; + goto out; } - memset(reply, 0, reply_size); sg_offset = (msg->u.head[0] >> 4) & 0x0f; - writel(i2o_config_driver.context, &msg->u.s.icntxt); - writel(i2o_cntxt_list_add(c, reply), &msg->u.s.tcntxt); - memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE); if (sg_offset) { struct sg_simple_element *sg; + struct i2o_dma *p; if (sg_offset * 4 >= size) { rcode = -EFAULT; @@ -865,22 +875,22 @@ static int i2o_cfg_passthru(unsigned long arg) goto sg_list_cleanup; } sg_size = sg[i].flag_count & 0xffffff; + p = &(sg_list[sg_index]); + if (i2o_dma_alloc(&c->pdev->dev, p, sg_size)) { /* Allocate memory for the transfer */ - p = kmalloc(sg_size, GFP_KERNEL); - if (!p) { printk(KERN_DEBUG "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", c->name, sg_size, i, sg_count); rcode = -ENOMEM; goto sg_list_cleanup; } - sg_list[sg_index++] = p; // sglist indexed with input frame, not our internal frame. + sg_index++; /* Copy in the user's SG buffer if necessary */ if (sg[i]. flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) { // TODO 64bit fix if (copy_from_user - (p, (void __user *)sg[i].addr_bus, + (p->virt, (void __user *)sg[i].addr_bus, sg_size)) { printk(KERN_DEBUG "%s: Could not copy SG buf %d FROM user\n", @@ -889,17 +899,19 @@ static int i2o_cfg_passthru(unsigned long arg) goto sg_list_cleanup; } } - //TODO 64bit fix - sg[i].addr_bus = virt_to_bus(p); + sg[i].addr_bus = p->phys; } } - rcode = i2o_msg_post_wait(c, m, 60); - if (rcode) + rcode = i2o_msg_post_wait(c, msg, 60); + msg = NULL; + if (rcode) { + reply[4] = ((u32) rcode) << 24; goto sg_list_cleanup; + } if (sg_offset) { - u32 msg[128]; + u32 rmsg[I2O_OUTBOUND_MSG_FRAME_SIZE]; /* Copy back the Scatter Gather buffers back to user space */ u32 j; // TODO 64bit fix @@ -907,7 +919,7 @@ static int i2o_cfg_passthru(unsigned long arg) int sg_size; // re-acquire the original message to handle correctly the sg copy operation - memset(&msg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4); + memset(&rmsg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4); // get user msg size in u32s if (get_user(size, &user_msg[0])) { rcode = -EFAULT; @@ -915,8 +927,13 @@ static int i2o_cfg_passthru(unsigned long arg) } size = size >> 16; size *= 4; + if (size > sizeof(rmsg)) { + rcode = -EFAULT; + goto sg_list_cleanup; + } + /* Copy in the user's I2O command */ - if (copy_from_user(msg, user_msg, size)) { + if (copy_from_user(rmsg, user_msg, size)) { rcode = -EFAULT; goto sg_list_cleanup; } @@ -924,7 +941,7 @@ static int i2o_cfg_passthru(unsigned long arg) (size - sg_offset * 4) / sizeof(struct sg_simple_element); // TODO 64bit fix - sg = (struct sg_simple_element *)(msg + sg_offset); + sg = (struct sg_simple_element *)(rmsg + sg_offset); for (j = 0; j < sg_count; j++) { /* Copy out the SG list to user's buffer if necessary */ if (! @@ -933,11 +950,11 @@ static int i2o_cfg_passthru(unsigned long arg) sg_size = sg[j].flag_count & 0xffffff; // TODO 64bit fix if (copy_to_user - ((void __user *)sg[j].addr_bus, sg_list[j], + ((void __user *)sg[j].addr_bus, sg_list[j].virt, sg_size)) { printk(KERN_WARNING "%s: Could not copy %p TO user %x\n", - c->name, sg_list[j], + c->name, sg_list[j].virt, sg[j].addr_bus); rcode = -EFAULT; goto sg_list_cleanup; @@ -946,6 +963,7 @@ static int i2o_cfg_passthru(unsigned long arg) } } +sg_list_cleanup: /* Copy back the reply to user space */ if (reply_size) { // we wrote our own values for context - now restore the user supplied ones @@ -962,12 +980,14 @@ static int i2o_cfg_passthru(unsigned long arg) } } - sg_list_cleanup: for (i = 0; i < sg_index; i++) - kfree(sg_list[i]); + i2o_dma_free(&c->pdev->dev, &sg_list[i]); - cleanup: +cleanup: kfree(reply); +out: + if (msg) + i2o_msg_nop(c, msg); return rcode; } #endif @@ -975,11 +995,11 @@ static int i2o_cfg_passthru(unsigned long arg) /* * IOCTL Handler */ -static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd, - unsigned long arg) +static long i2o_cfg_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) { int ret; + mutex_lock(&i2o_cfg_mutex); switch (cmd) { case I2OGETIOPS: ret = i2o_cfg_getiops(arg); @@ -1035,20 +1055,20 @@ static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd, osm_debug("unknown ioctl called!\n"); ret = -EINVAL; } - + mutex_unlock(&i2o_cfg_mutex); return ret; } static int cfg_open(struct inode *inode, struct file *file) { - struct i2o_cfg_info *tmp = - (struct i2o_cfg_info *)kmalloc(sizeof(struct i2o_cfg_info), + struct i2o_cfg_info *tmp = kmalloc(sizeof(struct i2o_cfg_info), GFP_KERNEL); unsigned long flags; if (!tmp) return -ENOMEM; + mutex_lock(&i2o_cfg_mutex); file->private_data = (void *)(i2o_cfg_info_id++); tmp->fp = file; tmp->fasync = NULL; @@ -1062,6 +1082,7 @@ static int cfg_open(struct inode *inode, struct file *file) spin_lock_irqsave(&i2o_config_lock, flags); open_files = tmp; spin_unlock_irqrestore(&i2o_config_lock, flags); + mutex_unlock(&i2o_cfg_mutex); return 0; } @@ -1070,53 +1091,44 @@ static int cfg_fasync(int fd, struct file *fp, int on) { ulong id = (ulong) fp->private_data; struct i2o_cfg_info *p; + int ret = -EBADF; + mutex_lock(&i2o_cfg_mutex); for (p = open_files; p; p = p->next) if (p->q_id == id) break; - if (!p) - return -EBADF; - - return fasync_helper(fd, fp, on, &p->fasync); + if (p) + ret = fasync_helper(fd, fp, on, &p->fasync); + mutex_unlock(&i2o_cfg_mutex); + return ret; } static int cfg_release(struct inode *inode, struct file *file) { ulong id = (ulong) file->private_data; - struct i2o_cfg_info *p1, *p2; + struct i2o_cfg_info *p, **q; unsigned long flags; - lock_kernel(); - p1 = p2 = NULL; - + mutex_lock(&i2o_cfg_mutex); spin_lock_irqsave(&i2o_config_lock, flags); - for (p1 = open_files; p1;) { - if (p1->q_id == id) { - - if (p1->fasync) - cfg_fasync(-1, file, 0); - if (p2) - p2->next = p1->next; - else - open_files = p1->next; - - kfree(p1); + for (q = &open_files; (p = *q) != NULL; q = &p->next) { + if (p->q_id == id) { + *q = p->next; + kfree(p); break; } - p2 = p1; - p1 = p1->next; } spin_unlock_irqrestore(&i2o_config_lock, flags); - unlock_kernel(); + mutex_unlock(&i2o_cfg_mutex); return 0; } -static struct file_operations config_fops = { +static const struct file_operations config_fops = { .owner = THIS_MODULE, .llseek = no_llseek, - .ioctl = i2o_cfg_ioctl, + .unlocked_ioctl = i2o_cfg_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = i2o_cfg_compat_ioctl, #endif diff --git a/drivers/message/i2o/i2o_lan.h b/drivers/message/i2o/i2o_lan.h deleted file mode 100644 index 561d63304d7..00000000000 --- a/drivers/message/i2o/i2o_lan.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * i2o_lan.h I2O LAN Class definitions - * - * I2O LAN CLASS OSM May 26th 2000 - * - * (C) Copyright 1999, 2000 University of Helsinki, - * Department of Computer Science - * - * This code is still under development / test. - * - * Author: Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI> - * Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI> - * Taneli Vähäkangas <Taneli.Vahakangas@cs.Helsinki.FI> - */ - -#ifndef _I2O_LAN_H -#define _I2O_LAN_H - -/* Default values for tunable parameters first */ - -#define I2O_LAN_MAX_BUCKETS_OUT 96 -#define I2O_LAN_BUCKET_THRESH 18 /* 9 buckets in one message */ -#define I2O_LAN_RX_COPYBREAK 200 -#define I2O_LAN_TX_TIMEOUT (1*HZ) -#define I2O_LAN_TX_BATCH_MODE 2 /* 2=automatic, 1=on, 0=off */ -#define I2O_LAN_EVENT_MASK 0 /* 0=None, 0xFFC00002=All */ - -/* LAN types */ -#define I2O_LAN_ETHERNET 0x0030 -#define I2O_LAN_100VG 0x0040 -#define I2O_LAN_TR 0x0050 -#define I2O_LAN_FDDI 0x0060 -#define I2O_LAN_FIBRE_CHANNEL 0x0070 -#define I2O_LAN_UNKNOWN 0x00000000 - -/* Connector types */ - -/* Ethernet */ -#define I2O_LAN_AUI (I2O_LAN_ETHERNET << 4) + 0x00000001 -#define I2O_LAN_10BASE5 (I2O_LAN_ETHERNET << 4) + 0x00000002 -#define I2O_LAN_FIORL (I2O_LAN_ETHERNET << 4) + 0x00000003 -#define I2O_LAN_10BASE2 (I2O_LAN_ETHERNET << 4) + 0x00000004 -#define I2O_LAN_10BROAD36 (I2O_LAN_ETHERNET << 4) + 0x00000005 -#define I2O_LAN_10BASE_T (I2O_LAN_ETHERNET << 4) + 0x00000006 -#define I2O_LAN_10BASE_FP (I2O_LAN_ETHERNET << 4) + 0x00000007 -#define I2O_LAN_10BASE_FB (I2O_LAN_ETHERNET << 4) + 0x00000008 -#define I2O_LAN_10BASE_FL (I2O_LAN_ETHERNET << 4) + 0x00000009 -#define I2O_LAN_100BASE_TX (I2O_LAN_ETHERNET << 4) + 0x0000000A -#define I2O_LAN_100BASE_FX (I2O_LAN_ETHERNET << 4) + 0x0000000B -#define I2O_LAN_100BASE_T4 (I2O_LAN_ETHERNET << 4) + 0x0000000C -#define I2O_LAN_1000BASE_SX (I2O_LAN_ETHERNET << 4) + 0x0000000D -#define I2O_LAN_1000BASE_LX (I2O_LAN_ETHERNET << 4) + 0x0000000E -#define I2O_LAN_1000BASE_CX (I2O_LAN_ETHERNET << 4) + 0x0000000F -#define I2O_LAN_1000BASE_T (I2O_LAN_ETHERNET << 4) + 0x00000010 - -/* AnyLAN */ -#define I2O_LAN_100VG_ETHERNET (I2O_LAN_100VG << 4) + 0x00000001 -#define I2O_LAN_100VG_TR (I2O_LAN_100VG << 4) + 0x00000002 - -/* Token Ring */ -#define I2O_LAN_4MBIT (I2O_LAN_TR << 4) + 0x00000001 -#define I2O_LAN_16MBIT (I2O_LAN_TR << 4) + 0x00000002 - -/* FDDI */ -#define I2O_LAN_125MBAUD (I2O_LAN_FDDI << 4) + 0x00000001 - -/* Fibre Channel */ -#define I2O_LAN_POINT_POINT (I2O_LAN_FIBRE_CHANNEL << 4) + 0x00000001 -#define I2O_LAN_ARB_LOOP (I2O_LAN_FIBRE_CHANNEL << 4) + 0x00000002 -#define I2O_LAN_PUBLIC_LOOP (I2O_LAN_FIBRE_CHANNEL << 4) + 0x00000003 -#define I2O_LAN_FABRIC (I2O_LAN_FIBRE_CHANNEL << 4) + 0x00000004 - -#define I2O_LAN_EMULATION 0x00000F00 -#define I2O_LAN_OTHER 0x00000F01 -#define I2O_LAN_DEFAULT 0xFFFFFFFF - -/* LAN class functions */ - -#define LAN_PACKET_SEND 0x3B -#define LAN_SDU_SEND 0x3D -#define LAN_RECEIVE_POST 0x3E -#define LAN_RESET 0x35 -#define LAN_SUSPEND 0x37 - -/* LAN DetailedStatusCode defines */ -#define I2O_LAN_DSC_SUCCESS 0x00 -#define I2O_LAN_DSC_DEVICE_FAILURE 0x01 -#define I2O_LAN_DSC_DESTINATION_NOT_FOUND 0x02 -#define I2O_LAN_DSC_TRANSMIT_ERROR 0x03 -#define I2O_LAN_DSC_TRANSMIT_ABORTED 0x04 -#define I2O_LAN_DSC_RECEIVE_ERROR 0x05 -#define I2O_LAN_DSC_RECEIVE_ABORTED 0x06 -#define I2O_LAN_DSC_DMA_ERROR 0x07 -#define I2O_LAN_DSC_BAD_PACKET_DETECTED 0x08 -#define I2O_LAN_DSC_OUT_OF_MEMORY 0x09 -#define I2O_LAN_DSC_BUCKET_OVERRUN 0x0A -#define I2O_LAN_DSC_IOP_INTERNAL_ERROR 0x0B -#define I2O_LAN_DSC_CANCELED 0x0C -#define I2O_LAN_DSC_INVALID_TRANSACTION_CONTEXT 0x0D -#define I2O_LAN_DSC_DEST_ADDRESS_DETECTED 0x0E -#define I2O_LAN_DSC_DEST_ADDRESS_OMITTED 0x0F -#define I2O_LAN_DSC_PARTIAL_PACKET_RETURNED 0x10 -#define I2O_LAN_DSC_SUSPENDED 0x11 - -struct i2o_packet_info { - u32 offset : 24; - u32 flags : 8; - u32 len : 24; - u32 status : 8; -}; - -struct i2o_bucket_descriptor { - u32 context; /* FIXME: 64bit support */ - struct i2o_packet_info packet_info[1]; -}; - -/* Event Indicator Mask Flags for LAN OSM */ - -#define I2O_LAN_EVT_LINK_DOWN 0x01 -#define I2O_LAN_EVT_LINK_UP 0x02 -#define I2O_LAN_EVT_MEDIA_CHANGE 0x04 - -#include <linux/netdevice.h> -#include <linux/fddidevice.h> - -struct i2o_lan_local { - u8 unit; - struct i2o_device *i2o_dev; - - struct fddi_statistics stats; /* see also struct net_device_stats */ - unsigned short (*type_trans)(struct sk_buff *, struct net_device *); - atomic_t buckets_out; /* nbr of unused buckets on DDM */ - atomic_t tx_out; /* outstanding TXes */ - u8 tx_count; /* packets in one TX message frame */ - u16 tx_max_out; /* DDM's Tx queue len */ - u8 sgl_max; /* max SGLs in one message frame */ - u32 m; /* IOP address of the batch msg frame */ - - struct work_struct i2o_batch_send_task; - int send_active; - struct sk_buff **i2o_fbl; /* Free bucket list (to reuse skbs) */ - int i2o_fbl_tail; - spinlock_t fbl_lock; - - spinlock_t tx_lock; - - u32 max_size_mc_table; /* max number of multicast addresses */ - - /* LAN OSM configurable parameters are here: */ - - u16 max_buckets_out; /* max nbr of buckets to send to DDM */ - u16 bucket_thresh; /* send more when this many used */ - u16 rx_copybreak; - - u8 tx_batch_mode; /* Set when using batch mode sends */ - u32 i2o_event_mask; /* To turn on interesting event flags */ -}; - -#endif /* _I2O_LAN_H */ diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c index d559a175836..b7d87cd227a 100644 --- a/drivers/message/i2o/i2o_proc.c +++ b/drivers/message/i2o/i2o_proc.c @@ -19,8 +19,8 @@ * * * Fixes/additions: - * Juha Sievänen (Juha.Sievanen@cs.Helsinki.FI), - * Auvo Häkkinen (Auvo.Hakkinen@cs.Helsinki.FI) + * Juha Sievänen (Juha.Sievanen@cs.Helsinki.FI), + * Auvo Häkkinen (Auvo.Hakkinen@cs.Helsinki.FI) * University of Helsinki, Department of Computer Science * LAN entries * Markus Lidel <Markus.Lidel@shadowconnect.com> @@ -28,7 +28,7 @@ */ #define OSM_NAME "proc-osm" -#define OSM_VERSION "1.145" +#define OSM_VERSION "1.316" #define OSM_DESCRIPTION "I2O ProcFS OSM" #define I2O_MAX_MODULES 4 @@ -40,6 +40,7 @@ #include <linux/kernel.h> #include <linux/pci.h> #include <linux/i2o.h> +#include <linux/slab.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/init.h> @@ -55,8 +56,8 @@ /* Structure used to define /proc entries */ typedef struct _i2o_proc_entry_t { char *name; /* entry name */ - mode_t mode; /* mode */ - struct file_operations *fops; /* open function */ + umode_t mode; /* mode */ + const struct file_operations *fops; /* open function */ } i2o_proc_entry; /* global I2O /proc/i2o entry */ @@ -111,10 +112,7 @@ static int print_serial_number(struct seq_file *seq, u8 * serialno, int max_len) break; case I2O_SNFORMAT_LAN48_MAC: /* LAN-48 MAC Address */ - seq_printf(seq, - "LAN-48 MAC address @ %02X:%02X:%02X:%02X:%02X:%02X", - serialno[2], serialno[3], - serialno[4], serialno[5], serialno[6], serialno[7]); + seq_printf(seq, "LAN-48 MAC address @ %pM", &serialno[2]); break; case I2O_SNFORMAT_WAN: /* WAN MAC Address */ @@ -126,10 +124,8 @@ static int print_serial_number(struct seq_file *seq, u8 * serialno, int max_len) case I2O_SNFORMAT_LAN64_MAC: /* LAN-64 MAC Address */ /* FIXME: Figure out what a LAN-64 address really looks like?? */ seq_printf(seq, - "LAN-64 MAC address @ [?:%02X:%02X:?] %02X:%02X:%02X:%02X:%02X:%02X", - serialno[8], serialno[9], - serialno[2], serialno[3], - serialno[4], serialno[5], serialno[6], serialno[7]); + "LAN-64 MAC address @ [?:%02X:%02X:?] %pM", + serialno[8], serialno[9], &serialno[2]); break; case I2O_SNFORMAT_DDM: /* I2O DDM */ @@ -163,7 +159,7 @@ static int print_serial_number(struct seq_file *seq, u8 * serialno, int max_len) * i2o_get_class_name - do i2o class name lookup * @class: class number * - * Return a descriptive string for an i2o class + * Return a descriptive string for an i2o class. */ static const char *i2o_get_class_name(int class) { @@ -259,9 +255,8 @@ static char *scsi_devices[] = { "Array Controller Device" }; -static char *chtostr(u8 * chars, int n) +static char *chtostr(char *tmp, u8 *chars, int n) { - char tmp[256]; tmp[0] = 0; return strncat(tmp, (char *)chars, n); } @@ -287,7 +282,6 @@ static char *bus_strings[] = { "Local Bus", "ISA", "EISA", - "MCA", "PCI", "PCMCIA", "NUBUS", @@ -355,18 +349,6 @@ static int i2o_seq_show_hrt(struct seq_file *seq, void *v) EisaSlotNumber); break; - case I2O_BUS_MCA: - seq_printf(seq, " IOBase: %0#6x,", - hrt->hrt_entry[i].bus.mca_bus. - McaBaseIOPort); - seq_printf(seq, " MemoryBase: %0#10x,", - hrt->hrt_entry[i].bus.mca_bus. - McaBaseMemoryAddress); - seq_printf(seq, " Slot: %0#4x,", - hrt->hrt_entry[i].bus.mca_bus. - McaSlotNumber); - break; - case I2O_BUS_PCI: seq_printf(seq, " Bus: %0#4x", hrt->hrt_entry[i].bus.pci_bus. @@ -808,6 +790,7 @@ static int i2o_seq_show_ddm_table(struct seq_file *seq, void *v) } *result; i2o_exec_execute_ddm_table ddm_table; + char tmp[28 + 1]; result = kmalloc(sizeof(*result), GFP_KERNEL); if (!result) @@ -843,7 +826,7 @@ static int i2o_seq_show_ddm_table(struct seq_file *seq, void *v) seq_printf(seq, "%-#7x", ddm_table.i2o_vendor_id); seq_printf(seq, "%-#8x", ddm_table.module_id); seq_printf(seq, "%-29s", - chtostr(ddm_table.module_name_version, 28)); + chtostr(tmp, ddm_table.module_name_version, 28)); seq_printf(seq, "%9d ", ddm_table.data_size); seq_printf(seq, "%8d", ddm_table.code_size); @@ -910,6 +893,7 @@ static int i2o_seq_show_drivers_stored(struct seq_file *seq, void *v) i2o_driver_result_table *result; i2o_driver_store_table *dst; + char tmp[28 + 1]; result = kmalloc(sizeof(i2o_driver_result_table), GFP_KERNEL); if (result == NULL) @@ -944,8 +928,9 @@ static int i2o_seq_show_drivers_stored(struct seq_file *seq, void *v) seq_printf(seq, "%-#7x", dst->i2o_vendor_id); seq_printf(seq, "%-#8x", dst->module_id); - seq_printf(seq, "%-29s", chtostr(dst->module_name_version, 28)); - seq_printf(seq, "%-9s", chtostr(dst->date, 8)); + seq_printf(seq, "%-29s", + chtostr(tmp, dst->module_name_version, 28)); + seq_printf(seq, "%-9s", chtostr(tmp, dst->date, 8)); seq_printf(seq, "%8d ", dst->module_size); seq_printf(seq, "%8d ", dst->mpb_size); seq_printf(seq, "0x%04x", dst->module_flags); @@ -1265,6 +1250,7 @@ static int i2o_seq_show_dev_identity(struct seq_file *seq, void *v) // == (allow) 512d bytes (max) static u16 *work16 = (u16 *) work32; int token; + char tmp[16 + 1]; token = i2o_parm_field_get(d, 0xF100, -1, &work32, sizeof(work32)); @@ -1277,13 +1263,13 @@ static int i2o_seq_show_dev_identity(struct seq_file *seq, void *v) seq_printf(seq, "Owner TID : %0#5x\n", work16[2]); seq_printf(seq, "Parent TID : %0#5x\n", work16[3]); seq_printf(seq, "Vendor info : %s\n", - chtostr((u8 *) (work32 + 2), 16)); + chtostr(tmp, (u8 *) (work32 + 2), 16)); seq_printf(seq, "Product info : %s\n", - chtostr((u8 *) (work32 + 6), 16)); + chtostr(tmp, (u8 *) (work32 + 6), 16)); seq_printf(seq, "Description : %s\n", - chtostr((u8 *) (work32 + 10), 16)); + chtostr(tmp, (u8 *) (work32 + 10), 16)); seq_printf(seq, "Product rev. : %s\n", - chtostr((u8 *) (work32 + 14), 8)); + chtostr(tmp, (u8 *) (work32 + 14), 8)); seq_printf(seq, "Serial number : "); print_serial_number(seq, (u8 *) (work32 + 16), @@ -1300,7 +1286,7 @@ static int i2o_seq_show_dev_name(struct seq_file *seq, void *v) { struct i2o_device *d = (struct i2o_device *)seq->private; - seq_printf(seq, "%s\n", d->device.bus_id); + seq_printf(seq, "%s\n", dev_name(&d->device)); return 0; } @@ -1320,6 +1306,8 @@ static int i2o_seq_show_ddm_identity(struct seq_file *seq, void *v) u8 pad[256]; // allow up to 256 byte (max) serial number } result; + char tmp[24 + 1]; + token = i2o_parm_field_get(d, 0xF101, -1, &result, sizeof(result)); if (token < 0) { @@ -1329,9 +1317,9 @@ static int i2o_seq_show_ddm_identity(struct seq_file *seq, void *v) seq_printf(seq, "Registering DDM TID : 0x%03x\n", result.ddm_tid); seq_printf(seq, "Module name : %s\n", - chtostr(result.module_name, 24)); + chtostr(tmp, result.module_name, 24)); seq_printf(seq, "Module revision : %s\n", - chtostr(result.module_rev, 8)); + chtostr(tmp, result.module_rev, 8)); seq_printf(seq, "Serial number : "); print_serial_number(seq, result.serial_number, sizeof(result) - 36); @@ -1355,6 +1343,8 @@ static int i2o_seq_show_uinfo(struct seq_file *seq, void *v) u8 instance_number[4]; } result; + char tmp[64 + 1]; + token = i2o_parm_field_get(d, 0xF102, -1, &result, sizeof(result)); if (token < 0) { @@ -1363,13 +1353,13 @@ static int i2o_seq_show_uinfo(struct seq_file *seq, void *v) } seq_printf(seq, "Device name : %s\n", - chtostr(result.device_name, 64)); + chtostr(tmp, result.device_name, 64)); seq_printf(seq, "Service name : %s\n", - chtostr(result.service_name, 64)); + chtostr(tmp, result.service_name, 64)); seq_printf(seq, "Physical name : %s\n", - chtostr(result.physical_location, 64)); + chtostr(tmp, result.physical_location, 64)); seq_printf(seq, "Instance number : %s\n", - chtostr(result.instance_number, 4)); + chtostr(tmp, result.instance_number, 4)); return 0; } @@ -1609,227 +1599,227 @@ static int i2o_seq_show_sensors(struct seq_file *seq, void *v) static int i2o_seq_open_hrt(struct inode *inode, struct file *file) { - return single_open(file, i2o_seq_show_hrt, PDE(inode)->data); + return single_open(file, i2o_seq_show_hrt, PDE_DATA(inode)); }; static int i2o_seq_open_lct(struct inode *inode, struct file *file) { - return single_open(file, i2o_seq_show_lct, PDE(inode)->data); + return single_open(file, i2o_seq_show_lct, PDE_DATA(inode)); }; static int i2o_seq_open_status(struct inode *inode, struct file *file) { - return single_open(file, i2o_seq_show_status, PDE(inode)->data); + return single_open(file, i2o_seq_show_status, PDE_DATA(inode)); }; static int i2o_seq_open_hw(struct inode *inode, struct file *file) { - return single_open(file, i2o_seq_show_hw, PDE(inode)->data); + return single_open(file, i2o_seq_show_hw, PDE_DATA(inode)); }; static int i2o_seq_open_ddm_table(struct inode *inode, struct file *file) { - return single_open(file, i2o_seq_show_ddm_table, PDE(inode)->data); + return single_open(file, i2o_seq_show_ddm_table, PDE_DATA(inode)); }; static int i2o_seq_open_driver_store(struct inode *inode, struct file *file) { - return single_open(file, i2o_seq_show_driver_store, PDE(inode)->data); + return single_open(file, i2o_seq_show_driver_store, PDE_DATA(inode)); }; static int i2o_seq_open_drivers_stored(struct inode *inode, struct file *file) { - return single_open(file, i2o_seq_show_drivers_stored, PDE(inode)->data); + return single_open(file, i2o_seq_show_drivers_stored, PDE_DATA(inode)); }; static int i2o_seq_open_groups(struct inode *inode, struct file *file) { - return single_open(file, i2o_seq_show_groups, PDE(inode)->data); + return single_open(file, i2o_seq_show_groups, PDE_DATA(inode)); }; static int i2o_seq_open_phys_device(struct inode *inode, struct file *file) { - return single_open(file, i2o_seq_show_phys_device, PDE(inode)->data); + return single_open(file, i2o_seq_show_phys_device, PDE_DATA(inode)); }; static int i2o_seq_open_claimed(struct inode *inode, struct file *file) { - return single_open(file, i2o_seq_show_claimed, PDE(inode)->data); + return single_open(file, i2o_seq_show_claimed, PDE_DATA(inode)); }; static int i2o_seq_open_users(struct inode *inode, struct file *file) { - return single_open(file, i2o_seq_show_users, PDE(inode)->data); + return single_open(file, i2o_seq_show_users, PDE_DATA(inode)); }; static int i2o_seq_open_priv_msgs(struct inode *inode, struct file *file) { - return single_open(file, i2o_seq_show_priv_msgs, PDE(inode)->data); + return single_open(file, i2o_seq_show_priv_msgs, PDE_DATA(inode)); }; static int i2o_seq_open_authorized_users(struct inode *inode, struct file *file) { return single_open(file, i2o_seq_show_authorized_users, - PDE(inode)->data); + PDE_DATA(inode)); }; static int i2o_seq_open_dev_identity(struct inode *inode, struct file *file) { - return single_open(file, i2o_seq_show_dev_identity, PDE(inode)->data); + return single_open(file, i2o_seq_show_dev_identity, PDE_DATA(inode)); }; static int i2o_seq_open_ddm_identity(struct inode *inode, struct file *file) { - return single_open(file, i2o_seq_show_ddm_identity, PDE(inode)->data); + return single_open(file, i2o_seq_show_ddm_identity, PDE_DATA(inode)); }; static int i2o_seq_open_uinfo(struct inode *inode, struct file *file) { - return single_open(file, i2o_seq_show_uinfo, PDE(inode)->data); + return single_open(file, i2o_seq_show_uinfo, PDE_DATA(inode)); }; static int i2o_seq_open_sgl_limits(struct inode *inode, struct file *file) { - return single_open(file, i2o_seq_show_sgl_limits, PDE(inode)->data); + return single_open(file, i2o_seq_show_sgl_limits, PDE_DATA(inode)); }; static int i2o_seq_open_sensors(struct inode *inode, struct file *file) { - return single_open(file, i2o_seq_show_sensors, PDE(inode)->data); + return single_open(file, i2o_seq_show_sensors, PDE_DATA(inode)); }; static int i2o_seq_open_dev_name(struct inode *inode, struct file *file) { - return single_open(file, i2o_seq_show_dev_name, PDE(inode)->data); + return single_open(file, i2o_seq_show_dev_name, PDE_DATA(inode)); }; -static struct file_operations i2o_seq_fops_lct = { +static const struct file_operations i2o_seq_fops_lct = { .open = i2o_seq_open_lct, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; -static struct file_operations i2o_seq_fops_hrt = { +static const struct file_operations i2o_seq_fops_hrt = { .open = i2o_seq_open_hrt, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; -static struct file_operations i2o_seq_fops_status = { +static const struct file_operations i2o_seq_fops_status = { .open = i2o_seq_open_status, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; -static struct file_operations i2o_seq_fops_hw = { +static const struct file_operations i2o_seq_fops_hw = { .open = i2o_seq_open_hw, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; -static struct file_operations i2o_seq_fops_ddm_table = { +static const struct file_operations i2o_seq_fops_ddm_table = { .open = i2o_seq_open_ddm_table, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; -static struct file_operations i2o_seq_fops_driver_store = { +static const struct file_operations i2o_seq_fops_driver_store = { .open = i2o_seq_open_driver_store, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; -static struct file_operations i2o_seq_fops_drivers_stored = { +static const struct file_operations i2o_seq_fops_drivers_stored = { .open = i2o_seq_open_drivers_stored, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; -static struct file_operations i2o_seq_fops_groups = { +static const struct file_operations i2o_seq_fops_groups = { .open = i2o_seq_open_groups, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; -static struct file_operations i2o_seq_fops_phys_device = { +static const struct file_operations i2o_seq_fops_phys_device = { .open = i2o_seq_open_phys_device, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; -static struct file_operations i2o_seq_fops_claimed = { +static const struct file_operations i2o_seq_fops_claimed = { .open = i2o_seq_open_claimed, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; -static struct file_operations i2o_seq_fops_users = { +static const struct file_operations i2o_seq_fops_users = { .open = i2o_seq_open_users, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; -static struct file_operations i2o_seq_fops_priv_msgs = { +static const struct file_operations i2o_seq_fops_priv_msgs = { .open = i2o_seq_open_priv_msgs, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; -static struct file_operations i2o_seq_fops_authorized_users = { +static const struct file_operations i2o_seq_fops_authorized_users = { .open = i2o_seq_open_authorized_users, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; -static struct file_operations i2o_seq_fops_dev_name = { +static const struct file_operations i2o_seq_fops_dev_name = { .open = i2o_seq_open_dev_name, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; -static struct file_operations i2o_seq_fops_dev_identity = { +static const struct file_operations i2o_seq_fops_dev_identity = { .open = i2o_seq_open_dev_identity, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; -static struct file_operations i2o_seq_fops_ddm_identity = { +static const struct file_operations i2o_seq_fops_ddm_identity = { .open = i2o_seq_open_ddm_identity, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; -static struct file_operations i2o_seq_fops_uinfo = { +static const struct file_operations i2o_seq_fops_uinfo = { .open = i2o_seq_open_uinfo, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; -static struct file_operations i2o_seq_fops_sgl_limits = { +static const struct file_operations i2o_seq_fops_sgl_limits = { .open = i2o_seq_open_sgl_limits, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; -static struct file_operations i2o_seq_fops_sensors = { +static const struct file_operations i2o_seq_fops_sensors = { .open = i2o_seq_open_sensors, .read = seq_read, .llseek = seq_lseek, @@ -1893,13 +1883,11 @@ static int i2o_proc_create_entries(struct proc_dir_entry *dir, struct proc_dir_entry *tmp; while (i2o_pe->name) { - tmp = create_proc_entry(i2o_pe->name, i2o_pe->mode, dir); + tmp = proc_create_data(i2o_pe->name, i2o_pe->mode, dir, + i2o_pe->fops, data); if (!tmp) return -1; - tmp->data = data; - tmp->proc_fops = i2o_pe->fops; - i2o_pe++; } @@ -1907,25 +1895,6 @@ static int i2o_proc_create_entries(struct proc_dir_entry *dir, } /** - * i2o_proc_subdir_remove - Remove child entries from a proc entry - * @dir: proc dir entry from which the childs should be removed - * - * Iterate over each i2o proc entry under dir and remove it. If the child - * also has entries, remove them too. - */ -static void i2o_proc_subdir_remove(struct proc_dir_entry *dir) -{ - struct proc_dir_entry *pe, *tmp; - pe = dir->subdir; - while (pe) { - tmp = pe->next; - i2o_proc_subdir_remove(pe); - remove_proc_entry(pe->name, dir); - pe = tmp; - } -}; - -/** * i2o_proc_device_add - Add an I2O device to the proc dir * @dir: proc dir entry to which the device should be added * @dev: I2O device which should be added @@ -1944,14 +1913,12 @@ static void i2o_proc_device_add(struct proc_dir_entry *dir, osm_debug("adding device /proc/i2o/%s/%s\n", dev->iop->name, buff); - devdir = proc_mkdir(buff, dir); + devdir = proc_mkdir_data(buff, 0, dir, dev); if (!devdir) { osm_warn("Could not allocate procdir!\n"); return; } - devdir->data = dev; - i2o_proc_create_entries(devdir, generic_dev_entries, dev); /* Inform core that we want updates about this device's status */ @@ -1985,12 +1952,10 @@ static int i2o_proc_iop_add(struct proc_dir_entry *dir, osm_debug("adding IOP /proc/i2o/%s\n", c->name); - iopdir = proc_mkdir(c->name, dir); + iopdir = proc_mkdir_data(c->name, 0, dir, c); if (!iopdir) return -1; - iopdir->data = c; - i2o_proc_create_entries(iopdir, i2o_proc_generic_iop_entries, c); list_for_each_entry(dev, &c->devices, list) @@ -2000,31 +1965,6 @@ static int i2o_proc_iop_add(struct proc_dir_entry *dir, } /** - * i2o_proc_iop_remove - Removes an I2O controller from the i2o proc tree - * @dir: parent proc dir entry - * @c: I2O controller which should be removed - * - * Iterate over each i2o proc entry and search controller c. If it is found - * remove it from the tree. - */ -static void i2o_proc_iop_remove(struct proc_dir_entry *dir, - struct i2o_controller *c) -{ - struct proc_dir_entry *pe, *tmp; - - pe = dir->subdir; - while (pe) { - tmp = pe->next; - if (pe->data == c) { - i2o_proc_subdir_remove(pe); - remove_proc_entry(pe->name, dir); - } - osm_debug("removing IOP /proc/i2o/%s\n", c->name); - pe = tmp; - } -} - -/** * i2o_proc_fs_create - Create the i2o proc fs. * * Iterate over each I2O controller and create the entries for it. @@ -2039,8 +1979,6 @@ static int __init i2o_proc_fs_create(void) if (!i2o_proc_dir_root) return -1; - i2o_proc_dir_root->owner = THIS_MODULE; - list_for_each_entry(c, &i2o_controllers, list) i2o_proc_iop_add(i2o_proc_dir_root, c); @@ -2056,12 +1994,7 @@ static int __init i2o_proc_fs_create(void) */ static int __exit i2o_proc_fs_destroy(void) { - struct i2o_controller *c; - - list_for_each_entry(c, &i2o_controllers, list) - i2o_proc_iop_remove(i2o_proc_dir_root, c); - - remove_proc_entry("i2o", NULL); + remove_proc_subtree("i2o", NULL); return 0; }; diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c index 9f1744c3933..1d31d7284cb 100644 --- a/drivers/message/i2o/i2o_scsi.c +++ b/drivers/message/i2o/i2o_scsi.c @@ -57,20 +57,17 @@ #include <linux/scatterlist.h> #include <asm/dma.h> -#include <asm/system.h> #include <asm/io.h> -#include <asm/atomic.h> +#include <linux/atomic.h> #include <scsi/scsi.h> #include <scsi/scsi_host.h> #include <scsi/scsi_device.h> #include <scsi/scsi_cmnd.h> -#include <scsi/scsi_request.h> #include <scsi/sg.h> -#include <scsi/sg_request.h> #define OSM_NAME "scsi-osm" -#define OSM_VERSION "1.282" +#define OSM_VERSION "1.316" #define OSM_DESCRIPTION "I2O SCSI Peripheral OSM" static struct i2o_driver i2o_scsi_driver; @@ -113,7 +110,7 @@ static struct i2o_scsi_host *i2o_scsi_host_alloc(struct i2o_controller *c) list_for_each_entry(i2o_dev, &c->devices, list) if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) { - if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) + if (!i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) && (type == 0x01)) /* SCSI bus */ max_channel++; } @@ -146,7 +143,7 @@ static struct i2o_scsi_host *i2o_scsi_host_alloc(struct i2o_controller *c) i = 0; list_for_each_entry(i2o_dev, &c->devices, list) if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) { - if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) + if (!i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) && (type == 0x01)) /* only SCSI bus */ i2o_shost->channel[i++] = i2o_dev; @@ -206,7 +203,7 @@ static int i2o_scsi_remove(struct device *dev) * i2o_scsi_probe - verify if dev is a I2O SCSI device and install it * @dev: device to verify if it is a I2O SCSI device * - * Retrieve channel, id and lun for I2O device. If everthing goes well + * Retrieve channel, id and lun for I2O device. If everything goes well * register the I2O device as SCSI device on the I2O SCSI controller. * * Returns 0 on success or negative error code on failure. @@ -222,7 +219,7 @@ static int i2o_scsi_probe(struct device *dev) u32 id = -1; u64 lun = -1; int channel = -1; - int i; + int i, rc; i2o_shost = i2o_scsi_get_host(c); if (!i2o_shost) @@ -238,13 +235,15 @@ static int i2o_scsi_probe(struct device *dev) u8 type; struct i2o_device *d = i2o_shost->channel[0]; - if (i2o_parm_field_get(d, 0x0000, 0, &type, 1) + if (!i2o_parm_field_get(d, 0x0000, 0, &type, 1) && (type == 0x01)) /* SCSI bus */ - if (i2o_parm_field_get(d, 0x0200, 4, &id, 4)) { + if (!i2o_parm_field_get(d, 0x0200, 4, &id, 4)) { channel = 0; if (i2o_dev->lct_data.class_id == I2O_CLASS_RANDOM_BLOCK_STORAGE) - lun = i2o_shost->lun++; + lun = + cpu_to_le64(i2o_shost-> + lun++); else lun = 0; } @@ -253,10 +252,10 @@ static int i2o_scsi_probe(struct device *dev) break; case I2O_CLASS_SCSI_PERIPHERAL: - if (i2o_parm_field_get(i2o_dev, 0x0000, 3, &id, 4) < 0) + if (i2o_parm_field_get(i2o_dev, 0x0000, 3, &id, 4)) return -EFAULT; - if (i2o_parm_field_get(i2o_dev, 0x0000, 4, &lun, 8) < 0) + if (i2o_parm_field_get(i2o_dev, 0x0000, 4, &lun, 8)) return -EFAULT; parent = i2o_iop_find_device(c, i2o_dev->lct_data.parent_tid); @@ -281,20 +280,22 @@ static int i2o_scsi_probe(struct device *dev) return -EFAULT; } - if (id >= scsi_host->max_id) { - osm_warn("SCSI device id (%d) >= max_id of I2O host (%d)", id, - scsi_host->max_id); + if (le32_to_cpu(id) >= scsi_host->max_id) { + osm_warn("SCSI device id (%d) >= max_id of I2O host (%d)", + le32_to_cpu(id), scsi_host->max_id); return -EFAULT; } - if (lun >= scsi_host->max_lun) { - osm_warn("SCSI device id (%d) >= max_lun of I2O host (%d)", - (unsigned int)lun, scsi_host->max_lun); + if (le64_to_cpu(lun) >= scsi_host->max_lun) { + osm_warn("SCSI device lun (%lu) >= max_lun of I2O host (%d)", + (long unsigned int)le64_to_cpu(lun), + scsi_host->max_lun); return -EFAULT; } scsi_dev = - __scsi_add_device(i2o_shost->scsi_host, channel, id, lun, i2o_dev); + __scsi_add_device(i2o_shost->scsi_host, channel, le32_to_cpu(id), + le64_to_cpu(lun), i2o_dev); if (IS_ERR(scsi_dev)) { osm_warn("can not add SCSI device %03x\n", @@ -302,13 +303,20 @@ static int i2o_scsi_probe(struct device *dev) return PTR_ERR(scsi_dev); } - sysfs_create_link(&i2o_dev->device.kobj, &scsi_dev->sdev_gendev.kobj, - "scsi"); + rc = sysfs_create_link(&i2o_dev->device.kobj, + &scsi_dev->sdev_gendev.kobj, "scsi"); + if (rc) + goto err; - osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %d\n", - i2o_dev->lct_data.tid, channel, id, (unsigned int)lun); + osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %ld\n", + i2o_dev->lct_data.tid, channel, le32_to_cpu(id), + (long unsigned int)le64_to_cpu(lun)); return 0; + +err: + scsi_remove_device(scsi_dev); + return rc; }; static const char *i2o_scsi_info(struct Scsi_Host *SChost) @@ -352,7 +360,7 @@ static int i2o_scsi_reply(struct i2o_controller *c, u32 m, */ error = le32_to_cpu(msg->body[0]); - osm_debug("Completed %ld\n", cmd->serial_number); + osm_debug("Completed %0x%p\n", cmd); cmd->result = error & 0xff; /* @@ -361,19 +369,15 @@ static int i2o_scsi_reply(struct i2o_controller *c, u32 m, */ if (cmd->result) memcpy(cmd->sense_buffer, &msg->body[3], - min(sizeof(cmd->sense_buffer), (size_t) 40)); + min(SCSI_SENSE_BUFFERSIZE, 40)); /* only output error code if AdapterStatus is not HBA_SUCCESS */ if ((error >> 8) & 0xff) osm_err("SCSI error %08x\n", error); dev = &c->pdev->dev; - if (cmd->use_sg) - dma_unmap_sg(dev, cmd->request_buffer, cmd->use_sg, - cmd->sc_data_direction); - else if (cmd->SCp.dma_handle) - dma_unmap_single(dev, cmd->SCp.dma_handle, cmd->request_bufflen, - cmd->sc_data_direction); + + scsi_dma_unmap(cmd); cmd->scsi_done(cmd); @@ -385,7 +389,7 @@ static int i2o_scsi_reply(struct i2o_controller *c, u32 m, * @i2o_dev: the I2O device which was added * * If a I2O device is added we catch the notification, because I2O classes - * other then SCSI peripheral will not be received through + * other than SCSI peripheral will not be received through * i2o_scsi_probe(). */ static void i2o_scsi_notify_device_add(struct i2o_device *i2o_dev) @@ -402,8 +406,7 @@ static void i2o_scsi_notify_device_add(struct i2o_device *i2o_dev) }; /** - * i2o_scsi_notify_device_remove - Retrieve notifications of removed - * devices + * i2o_scsi_notify_device_remove - Retrieve notifications of removed devices * @i2o_dev: the I2O device which was removed * * If a I2O device is removed, we catch the notification to remove the @@ -423,8 +426,7 @@ static void i2o_scsi_notify_device_remove(struct i2o_device *i2o_dev) }; /** - * i2o_scsi_notify_controller_add - Retrieve notifications of added - * controllers + * i2o_scsi_notify_controller_add - Retrieve notifications of added controllers * @c: the controller which was added * * If a I2O controller is added, we catch the notification to add a @@ -454,8 +456,7 @@ static void i2o_scsi_notify_controller_add(struct i2o_controller *c) }; /** - * i2o_scsi_notify_controller_remove - Retrieve notifications of removed - * controllers + * i2o_scsi_notify_controller_remove - Retrieve notifications of removed controllers * @c: the controller which was removed * * If a I2O controller is removed, we catch the notification to remove the @@ -504,14 +505,13 @@ static struct i2o_driver i2o_scsi_driver = { * Locks: takes the controller lock on error path only */ -static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, +static int i2o_scsi_queuecommand_lck(struct scsi_cmnd *SCpnt, void (*done) (struct scsi_cmnd *)) { struct i2o_controller *c; struct i2o_device *i2o_dev; int tid; - struct i2o_message __iomem *msg; - u32 m; + struct i2o_message *msg; /* * ENABLE_DISCONNECT * SIMPLE_TAG @@ -519,7 +519,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, */ u32 scsi_flags = 0x20a00000; u32 sgl_offset; - u32 __iomem *mptr; + u32 *mptr; u32 cmd = I2O_CMD_SCSI_EXEC << 24; int rc = 0; @@ -527,7 +527,6 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, * Do the incoming paperwork */ i2o_dev = SCpnt->device->hostdata; - c = i2o_dev->iop; SCpnt->scsi_done = done; @@ -537,7 +536,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, done(SCpnt); goto exit; } - + c = i2o_dev->iop; tid = i2o_dev->lct_data.tid; osm_debug("qcmd: Tid = %03x\n", tid); @@ -576,14 +575,15 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, * throw it back to the scsi layer */ - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) { + msg = i2o_msg_get(c); + if (IS_ERR(msg)) { rc = SCSI_MLQUEUE_HOST_BUSY; goto exit; } mptr = &msg->body[0]; +#if 0 /* this code can't work */ #ifdef CONFIG_I2O_EXT_ADAPTEC if (c->adaptec) { u32 adpt_flags = 0; @@ -617,16 +617,17 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, if (sgl_offset == SGL_OFFSET_10) sgl_offset = SGL_OFFSET_12; cmd = I2O_CMD_PRIVATE << 24; - writel(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC, mptr++); - writel(adpt_flags | tid, mptr++); + *mptr++ = cpu_to_le32(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC); + *mptr++ = cpu_to_le32(adpt_flags | tid); } #endif +#endif - writel(cmd | HOST_TID << 12 | tid, &msg->u.head[1]); - writel(i2o_scsi_driver.context, &msg->u.s.icntxt); + msg->u.head[1] = cpu_to_le32(cmd | HOST_TID << 12 | tid); + msg->u.s.icntxt = cpu_to_le32(i2o_scsi_driver.context); /* We want the SCSI control block back */ - writel(i2o_cntxt_list_add(c, SCpnt), &msg->u.s.tcntxt); + msg->u.s.tcntxt = cpu_to_le32(i2o_cntxt_list_add(c, SCpnt)); /* LSI_920_PCI_QUIRK * @@ -649,50 +650,46 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, } */ - writel(scsi_flags | SCpnt->cmd_len, mptr++); + *mptr++ = cpu_to_le32(scsi_flags | SCpnt->cmd_len); /* Write SCSI command into the message - always 16 byte block */ - memcpy_toio(mptr, SCpnt->cmnd, 16); + memcpy(mptr, SCpnt->cmnd, 16); mptr += 4; if (sgl_offset != SGL_OFFSET_0) { /* write size of data addressed by SGL */ - writel(SCpnt->request_bufflen, mptr++); + *mptr++ = cpu_to_le32(scsi_bufflen(SCpnt)); /* Now fill in the SGList and command */ - if (SCpnt->use_sg) { - if (!i2o_dma_map_sg(c, SCpnt->request_buffer, - SCpnt->use_sg, + + if (scsi_sg_count(SCpnt)) { + if (!i2o_dma_map_sg(c, scsi_sglist(SCpnt), + scsi_sg_count(SCpnt), SCpnt->sc_data_direction, &mptr)) goto nomem; - } else { - SCpnt->SCp.dma_handle = - i2o_dma_map_single(c, SCpnt->request_buffer, - SCpnt->request_bufflen, - SCpnt->sc_data_direction, &mptr); - if (dma_mapping_error(SCpnt->SCp.dma_handle)) - goto nomem; } } /* Stick the headers on */ - writel(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset, - &msg->u.head[0]); + msg->u.head[0] = + cpu_to_le32(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset); /* Queue the message */ - i2o_msg_post(c, m); + i2o_msg_post(c, msg); - osm_debug("Issued %ld\n", SCpnt->serial_number); + osm_debug("Issued %0x%p\n", SCpnt); return 0; nomem: rc = -ENOMEM; - i2o_msg_nop(c, m); + i2o_msg_nop(c, msg); exit: return rc; -}; +} + +static DEF_SCSI_QCMD(i2o_scsi_queuecommand) /** * i2o_scsi_abort - abort a running command @@ -709,8 +706,7 @@ static int i2o_scsi_abort(struct scsi_cmnd *SCpnt) { struct i2o_device *i2o_dev; struct i2o_controller *c; - struct i2o_message __iomem *msg; - u32 m; + struct i2o_message *msg; int tid; int status = FAILED; @@ -720,16 +716,16 @@ static int i2o_scsi_abort(struct scsi_cmnd *SCpnt) c = i2o_dev->iop; tid = i2o_dev->lct_data.tid; - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) return SCSI_MLQUEUE_HOST_BUSY; - writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); - writel(I2O_CMD_SCSI_ABORT << 24 | HOST_TID << 12 | tid, - &msg->u.head[1]); - writel(i2o_cntxt_list_get_ptr(c, SCpnt), &msg->body[0]); + msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_SCSI_ABORT << 24 | HOST_TID << 12 | tid); + msg->body[0] = cpu_to_le32(i2o_cntxt_list_get_ptr(c, SCpnt)); - if (i2o_msg_post_wait(c, m, I2O_TIMEOUT_SCSI_SCB_ABORT)) + if (!i2o_msg_post_wait(c, msg, I2O_TIMEOUT_SCSI_SCB_ABORT)) status = SUCCESS; return status; @@ -742,7 +738,7 @@ static int i2o_scsi_abort(struct scsi_cmnd *SCpnt) * @capacity: size in sectors * @ip: geometry array * - * This is anyones guess quite frankly. We use the same rules everyone + * This is anyone's guess quite frankly. We use the same rules everyone * else appears to and hope. It seems to work. */ diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c index 61b837de4b6..92752fb5b2d 100644 --- a/drivers/message/i2o/iop.c +++ b/drivers/message/i2o/iop.c @@ -15,11 +15,11 @@ * * Fixes/additions: * Philipp Rumpf - * Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI> - * Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI> + * Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI> + * Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI> * Deepak Saxena <deepak@plexity.net> * Boji T Kannanthanam <boji.t.kannanthanam@intel.com> - * Alan Cox <alan@redhat.com>: + * Alan Cox <alan@lxorguk.ukuu.org.uk>: * Ported to Linux 2.5. * Markus Lidel <Markus.Lidel@shadowconnect.com>: * Minor fixes for 2.6. @@ -29,10 +29,11 @@ #include <linux/i2o.h> #include <linux/delay.h> #include <linux/sched.h> +#include <linux/slab.h> #include "core.h" #define OSM_NAME "i2o" -#define OSM_VERSION "1.288" +#define OSM_VERSION "1.325" #define OSM_DESCRIPTION "I2O subsystem" /* global I2O controller list */ @@ -47,30 +48,8 @@ static struct i2o_dma i2o_systab; static int i2o_hrt_get(struct i2o_controller *c); /** - * i2o_msg_nop - Returns a message which is not used - * @c: I2O controller from which the message was created - * @m: message which should be returned - * - * If you fetch a message via i2o_msg_get, and can't use it, you must - * return the message with this function. Otherwise the message frame - * is lost. - */ -void i2o_msg_nop(struct i2o_controller *c, u32 m) -{ - struct i2o_message __iomem *msg = i2o_msg_in_to_virt(c, m); - - writel(THREE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); - writel(I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | ADAPTER_TID, - &msg->u.head[1]); - writel(0, &msg->u.head[2]); - writel(0, &msg->u.head[3]); - i2o_msg_post(c, m); -}; - -/** * i2o_msg_get_wait - obtain an I2O message from the IOP * @c: I2O controller - * @msg: pointer to a I2O message pointer * @wait: how long to wait until timeout * * This function waits up to wait seconds for a message slot to be @@ -81,23 +60,21 @@ void i2o_msg_nop(struct i2o_controller *c, u32 m) * address from the read port (see the i2o spec). If no message is * available returns I2O_QUEUE_EMPTY and msg is leaved untouched. */ -u32 i2o_msg_get_wait(struct i2o_controller *c, - struct i2o_message __iomem ** msg, int wait) +struct i2o_message *i2o_msg_get_wait(struct i2o_controller *c, int wait) { unsigned long timeout = jiffies + wait * HZ; - u32 m; + struct i2o_message *msg; - while ((m = i2o_msg_get(c, msg)) == I2O_QUEUE_EMPTY) { + while (IS_ERR(msg = i2o_msg_get(c))) { if (time_after(jiffies, timeout)) { osm_debug("%s: Timeout waiting for message frame.\n", c->name); - return I2O_QUEUE_EMPTY; + return ERR_PTR(-ETIMEDOUT); } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } - return m; + return msg; }; #if BITS_PER_LONG == 64 @@ -156,7 +133,7 @@ u32 i2o_cntxt_list_add(struct i2o_controller * c, void *ptr) * Removes a previously added pointer from the context list and returns * the matching context id. * - * Returns context id on succes or 0 on failure. + * Returns context id on success or 0 on failure. */ u32 i2o_cntxt_list_remove(struct i2o_controller * c, void *ptr) { @@ -222,7 +199,7 @@ void *i2o_cntxt_list_get(struct i2o_controller *c, u32 context) * @c: controller to which the context list belong * @ptr: pointer to which the context id should be fetched * - * Returns context id which matches to the pointer on succes or 0 on + * Returns context id which matches to the pointer on success or 0 on * failure. */ u32 i2o_cntxt_list_get_ptr(struct i2o_controller * c, void *ptr) @@ -302,8 +279,7 @@ struct i2o_device *i2o_iop_find_device(struct i2o_controller *c, u16 tid) */ static int i2o_iop_quiesce(struct i2o_controller *c) { - struct i2o_message __iomem *msg; - u32 m; + struct i2o_message *msg; i2o_status_block *sb = c->status_block.virt; int rc; @@ -314,16 +290,17 @@ static int i2o_iop_quiesce(struct i2o_controller *c) (sb->iop_state != ADAPTER_STATE_OPERATIONAL)) return 0; - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -ETIMEDOUT; + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); - writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); - writel(I2O_CMD_SYS_QUIESCE << 24 | HOST_TID << 12 | ADAPTER_TID, - &msg->u.head[1]); + msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_SYS_QUIESCE << 24 | HOST_TID << 12 | + ADAPTER_TID); /* Long timeout needed for quiesce if lots of devices */ - if ((rc = i2o_msg_post_wait(c, m, 240))) + if ((rc = i2o_msg_post_wait(c, msg, 240))) osm_info("%s: Unable to quiesce (status=%#x).\n", c->name, -rc); else osm_debug("%s: Quiesced.\n", c->name); @@ -343,8 +320,7 @@ static int i2o_iop_quiesce(struct i2o_controller *c) */ static int i2o_iop_enable(struct i2o_controller *c) { - struct i2o_message __iomem *msg; - u32 m; + struct i2o_message *msg; i2o_status_block *sb = c->status_block.virt; int rc; @@ -354,16 +330,17 @@ static int i2o_iop_enable(struct i2o_controller *c) if (sb->iop_state != ADAPTER_STATE_READY) return -EINVAL; - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -ETIMEDOUT; + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); - writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); - writel(I2O_CMD_SYS_ENABLE << 24 | HOST_TID << 12 | ADAPTER_TID, - &msg->u.head[1]); + msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_SYS_ENABLE << 24 | HOST_TID << 12 | + ADAPTER_TID); /* How long of a timeout do we need? */ - if ((rc = i2o_msg_post_wait(c, m, 240))) + if ((rc = i2o_msg_post_wait(c, msg, 240))) osm_err("%s: Could not enable (status=%#x).\n", c->name, -rc); else osm_debug("%s: Enabled.\n", c->name); @@ -414,22 +391,22 @@ static inline void i2o_iop_enable_all(void) */ static int i2o_iop_clear(struct i2o_controller *c) { - struct i2o_message __iomem *msg; - u32 m; + struct i2o_message *msg; int rc; - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -ETIMEDOUT; + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); /* Quiesce all IOPs first */ i2o_iop_quiesce_all(); - writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); - writel(I2O_CMD_ADAPTER_CLEAR << 24 | HOST_TID << 12 | ADAPTER_TID, - &msg->u.head[1]); + msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_ADAPTER_CLEAR << 24 | HOST_TID << 12 | + ADAPTER_TID); - if ((rc = i2o_msg_post_wait(c, m, 30))) + if ((rc = i2o_msg_post_wait(c, msg, 30))) osm_info("%s: Unable to clear (status=%#x).\n", c->name, -rc); else osm_debug("%s: Cleared.\n", c->name); @@ -447,13 +424,13 @@ static int i2o_iop_clear(struct i2o_controller *c) * Clear and (re)initialize IOP's outbound queue and post the message * frames to the IOP. * - * Returns 0 on success or a negative errno code on failure. + * Returns 0 on success or negative error code on failure. */ static int i2o_iop_init_outbound_queue(struct i2o_controller *c) { - volatile u8 *status = c->status.virt; u32 m; - struct i2o_message __iomem *msg; + volatile u8 *status = c->status.virt; + struct i2o_message *msg; ulong timeout; int i; @@ -461,23 +438,24 @@ static int i2o_iop_init_outbound_queue(struct i2o_controller *c) memset(c->status.virt, 0, 4); - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -ETIMEDOUT; - - writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6, &msg->u.head[0]); - writel(I2O_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 | ADAPTER_TID, - &msg->u.head[1]); - writel(i2o_exec_driver.context, &msg->u.s.icntxt); - writel(0x00000000, &msg->u.s.tcntxt); - writel(PAGE_SIZE, &msg->body[0]); + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 | + ADAPTER_TID); + msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context); + msg->u.s.tcntxt = cpu_to_le32(0x00000000); + msg->body[0] = cpu_to_le32(PAGE_SIZE); /* Outbound msg frame size in words and Initcode */ - writel(I2O_OUTBOUND_MSG_FRAME_SIZE << 16 | 0x80, &msg->body[1]); - writel(0xd0000004, &msg->body[2]); - writel(i2o_dma_low(c->status.phys), &msg->body[3]); - writel(i2o_dma_high(c->status.phys), &msg->body[4]); + msg->body[1] = cpu_to_le32(I2O_OUTBOUND_MSG_FRAME_SIZE << 16 | 0x80); + msg->body[2] = cpu_to_le32(0xd0000004); + msg->body[3] = cpu_to_le32(i2o_dma_low(c->status.phys)); + msg->body[4] = cpu_to_le32(i2o_dma_high(c->status.phys)); - i2o_msg_post(c, m); + i2o_msg_post(c, msg); timeout = jiffies + I2O_TIMEOUT_INIT_OUTBOUND_QUEUE * HZ; while (*status <= I2O_CMD_IN_PROGRESS) { @@ -485,8 +463,7 @@ static int i2o_iop_init_outbound_queue(struct i2o_controller *c) osm_warn("%s: Timeout Initializing\n", c->name); return -ETIMEDOUT; } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } m = c->out_queue.phys; @@ -513,34 +490,34 @@ static int i2o_iop_init_outbound_queue(struct i2o_controller *c) static int i2o_iop_reset(struct i2o_controller *c) { volatile u8 *status = c->status.virt; - struct i2o_message __iomem *msg; - u32 m; + struct i2o_message *msg; unsigned long timeout; i2o_status_block *sb = c->status_block.virt; int rc = 0; osm_debug("%s: Resetting controller\n", c->name); - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -ETIMEDOUT; + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); memset(c->status_block.virt, 0, 8); /* Quiesce all IOPs first */ i2o_iop_quiesce_all(); - writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); - writel(I2O_CMD_ADAPTER_RESET << 24 | HOST_TID << 12 | ADAPTER_TID, - &msg->u.head[1]); - writel(i2o_exec_driver.context, &msg->u.s.icntxt); - writel(0, &msg->u.s.tcntxt); //FIXME: use reasonable transaction context - writel(0, &msg->body[0]); - writel(0, &msg->body[1]); - writel(i2o_dma_low(c->status.phys), &msg->body[2]); - writel(i2o_dma_high(c->status.phys), &msg->body[3]); + msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_ADAPTER_RESET << 24 | HOST_TID << 12 | + ADAPTER_TID); + msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context); + msg->u.s.tcntxt = cpu_to_le32(0x00000000); + msg->body[0] = cpu_to_le32(0x00000000); + msg->body[1] = cpu_to_le32(0x00000000); + msg->body[2] = cpu_to_le32(i2o_dma_low(c->status.phys)); + msg->body[3] = cpu_to_le32(i2o_dma_high(c->status.phys)); - i2o_msg_post(c, m); + i2o_msg_post(c, msg); /* Wait for a reply */ timeout = jiffies + I2O_TIMEOUT_RESET * HZ; @@ -548,8 +525,7 @@ static int i2o_iop_reset(struct i2o_controller *c) if (time_after(jiffies, timeout)) break; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } switch (*status) { @@ -564,25 +540,21 @@ static int i2o_iop_reset(struct i2o_controller *c) * which is indeterminate. We need to wait until the IOP has * rebooted before we can let the system talk to it. We read * the inbound Free_List until a message is available. If we - * can't read one in the given ammount of time, we assume the + * can't read one in the given amount of time, we assume the * IOP could not reboot properly. */ osm_debug("%s: Reset in progress, waiting for reboot...\n", c->name); - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET); - while (m == I2O_QUEUE_EMPTY) { + while (IS_ERR(msg = i2o_msg_get_wait(c, I2O_TIMEOUT_RESET))) { if (time_after(jiffies, timeout)) { osm_err("%s: IOP reset timeout.\n", c->name); - rc = -ETIMEDOUT; + rc = PTR_ERR(msg); goto exit; } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); - - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET); + schedule_timeout_uninterruptible(1); } - i2o_msg_nop(c, m); + i2o_msg_nop(c, msg); /* from here all quiesce commands are safe */ c->no_quiesce = 0; @@ -680,6 +652,44 @@ static int i2o_iop_activate(struct i2o_controller *c) return i2o_hrt_get(c); }; +static void i2o_res_alloc(struct i2o_controller *c, unsigned long flags) +{ + i2o_status_block *sb = c->status_block.virt; + struct resource *res = &c->mem_resource; + resource_size_t size, align; + int err; + + res->name = c->pdev->bus->name; + res->flags = flags; + res->start = 0; + res->end = 0; + osm_info("%s: requires private memory resources.\n", c->name); + + if (flags & IORESOURCE_MEM) { + size = sb->desired_mem_size; + align = 1 << 20; /* unspecified, use 1Mb and play safe */ + } else { + size = sb->desired_io_size; + align = 1 << 12; /* unspecified, use 4Kb and play safe */ + } + + err = pci_bus_alloc_resource(c->pdev->bus, res, size, align, 0, 0, + NULL, NULL); + if (err < 0) + return; + + if (flags & IORESOURCE_MEM) { + c->mem_alloc = 1; + sb->current_mem_size = resource_size(res); + sb->current_mem_base = res->start; + } else if (flags & IORESOURCE_IO) { + c->io_alloc = 1; + sb->current_io_size = resource_size(res); + sb->current_io_base = res->start; + } + osm_info("%s: allocated PCI space %pR\n", c->name, res); +} + /** * i2o_iop_systab_set - Set the I2O System Table of the specified IOP * @c: I2O controller to which the system table should be send @@ -690,90 +700,49 @@ static int i2o_iop_activate(struct i2o_controller *c) */ static int i2o_iop_systab_set(struct i2o_controller *c) { - struct i2o_message __iomem *msg; - u32 m; + struct i2o_message *msg; i2o_status_block *sb = c->status_block.virt; struct device *dev = &c->pdev->dev; - struct resource *root; int rc; - if (sb->current_mem_size < sb->desired_mem_size) { - struct resource *res = &c->mem_resource; - res->name = c->pdev->bus->name; - res->flags = IORESOURCE_MEM; - res->start = 0; - res->end = 0; - osm_info("%s: requires private memory resources.\n", c->name); - root = pci_find_parent_resource(c->pdev, res); - if (root == NULL) - osm_warn("%s: Can't find parent resource!\n", c->name); - if (root && allocate_resource(root, res, sb->desired_mem_size, sb->desired_mem_size, sb->desired_mem_size, 1 << 20, /* Unspecified, so use 1Mb and play safe */ - NULL, NULL) >= 0) { - c->mem_alloc = 1; - sb->current_mem_size = 1 + res->end - res->start; - sb->current_mem_base = res->start; - osm_info("%s: allocated %ld bytes of PCI memory at " - "0x%08lX.\n", c->name, - 1 + res->end - res->start, res->start); - } - } + if (sb->current_mem_size < sb->desired_mem_size) + i2o_res_alloc(c, IORESOURCE_MEM); - if (sb->current_io_size < sb->desired_io_size) { - struct resource *res = &c->io_resource; - res->name = c->pdev->bus->name; - res->flags = IORESOURCE_IO; - res->start = 0; - res->end = 0; - osm_info("%s: requires private memory resources.\n", c->name); - root = pci_find_parent_resource(c->pdev, res); - if (root == NULL) - osm_warn("%s: Can't find parent resource!\n", c->name); - if (root && allocate_resource(root, res, sb->desired_io_size, sb->desired_io_size, sb->desired_io_size, 1 << 20, /* Unspecified, so use 1Mb and play safe */ - NULL, NULL) >= 0) { - c->io_alloc = 1; - sb->current_io_size = 1 + res->end - res->start; - sb->current_mem_base = res->start; - osm_info("%s: allocated %ld bytes of PCI I/O at 0x%08lX" - ".\n", c->name, 1 + res->end - res->start, - res->start); - } - } + if (sb->current_io_size < sb->desired_io_size) + i2o_res_alloc(c, IORESOURCE_IO); - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -ETIMEDOUT; + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); i2o_systab.phys = dma_map_single(dev, i2o_systab.virt, i2o_systab.len, PCI_DMA_TODEVICE); if (!i2o_systab.phys) { - i2o_msg_nop(c, m); + i2o_msg_nop(c, msg); return -ENOMEM; } - writel(I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6, &msg->u.head[0]); - writel(I2O_CMD_SYS_TAB_SET << 24 | HOST_TID << 12 | ADAPTER_TID, - &msg->u.head[1]); + msg->u.head[0] = cpu_to_le32(I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_SYS_TAB_SET << 24 | HOST_TID << 12 | + ADAPTER_TID); /* * Provide three SGL-elements: * System table (SysTab), Private memory space declaration and * Private i/o space declaration - * - * FIXME: is this still true? - * Nasty one here. We can't use dma_alloc_coherent to send the - * same table to everyone. We have to go remap it for them all */ - writel(c->unit + 2, &msg->body[0]); - writel(0, &msg->body[1]); - writel(0x54000000 | i2o_systab.len, &msg->body[2]); - writel(i2o_systab.phys, &msg->body[3]); - writel(0x54000000 | sb->current_mem_size, &msg->body[4]); - writel(sb->current_mem_base, &msg->body[5]); - writel(0xd4000000 | sb->current_io_size, &msg->body[6]); - writel(sb->current_io_base, &msg->body[6]); + msg->body[0] = cpu_to_le32(c->unit + 2); + msg->body[1] = cpu_to_le32(0x00000000); + msg->body[2] = cpu_to_le32(0x54000000 | i2o_systab.len); + msg->body[3] = cpu_to_le32(i2o_systab.phys); + msg->body[4] = cpu_to_le32(0x54000000 | sb->current_mem_size); + msg->body[5] = cpu_to_le32(sb->current_mem_base); + msg->body[6] = cpu_to_le32(0xd4000000 | sb->current_io_size); + msg->body[6] = cpu_to_le32(sb->current_io_base); - rc = i2o_msg_post_wait(c, m, 120); + rc = i2o_msg_post_wait(c, msg, 120); dma_unmap_single(dev, i2o_systab.phys, i2o_systab.len, PCI_DMA_TODEVICE); @@ -784,8 +753,6 @@ static int i2o_iop_systab_set(struct i2o_controller *c) else osm_debug("%s: SysTab set.\n", c->name); - i2o_status_get(c); // Entered READY state - return rc; } @@ -795,7 +762,7 @@ static int i2o_iop_systab_set(struct i2o_controller *c) * * Send the system table and enable the I2O controller. * - * Returns 0 on success or negativer error code on failure. + * Returns 0 on success or negative error code on failure. */ static int i2o_iop_online(struct i2o_controller *c) { @@ -834,13 +801,10 @@ void i2o_iop_remove(struct i2o_controller *c) list_for_each_entry_safe(dev, tmp, &c->devices, list) i2o_device_remove(dev); - class_device_unregister(c->classdev); device_del(&c->device); /* Ask the IOP to switch to RESET state */ i2o_iop_reset(c); - - put_device(&c->device); } /** @@ -873,12 +837,11 @@ static int i2o_systab_build(void) i2o_systab.len = sizeof(struct i2o_sys_tbl) + num_controllers * sizeof(struct i2o_sys_tbl_entry); - systab = i2o_systab.virt = kmalloc(i2o_systab.len, GFP_KERNEL); + systab = i2o_systab.virt = kzalloc(i2o_systab.len, GFP_KERNEL); if (!systab) { osm_err("unable to allocate memory for System Table\n"); return -ENOMEM; } - memset(systab, 0, i2o_systab.len); systab->version = I2OVERSION; systab->change_ind = change_ind + 1; @@ -952,34 +915,34 @@ static int i2o_parse_hrt(struct i2o_controller *c) * status block. The status block could then be accessed through * c->status_block. * - * Returns 0 on sucess or negative error code on failure. + * Returns 0 on success or negative error code on failure. */ int i2o_status_get(struct i2o_controller *c) { - struct i2o_message __iomem *msg; - u32 m; + struct i2o_message *msg; volatile u8 *status_block; unsigned long timeout; status_block = (u8 *) c->status_block.virt; memset(c->status_block.virt, 0, sizeof(i2o_status_block)); - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -ETIMEDOUT; + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); - writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); - writel(I2O_CMD_STATUS_GET << 24 | HOST_TID << 12 | ADAPTER_TID, - &msg->u.head[1]); - writel(i2o_exec_driver.context, &msg->u.s.icntxt); - writel(0, &msg->u.s.tcntxt); // FIXME: use resonable transaction context - writel(0, &msg->body[0]); - writel(0, &msg->body[1]); - writel(i2o_dma_low(c->status_block.phys), &msg->body[2]); - writel(i2o_dma_high(c->status_block.phys), &msg->body[3]); - writel(sizeof(i2o_status_block), &msg->body[4]); /* always 88 bytes */ + msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_STATUS_GET << 24 | HOST_TID << 12 | + ADAPTER_TID); + msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context); + msg->u.s.tcntxt = cpu_to_le32(0x00000000); + msg->body[0] = cpu_to_le32(0x00000000); + msg->body[1] = cpu_to_le32(0x00000000); + msg->body[2] = cpu_to_le32(i2o_dma_low(c->status_block.phys)); + msg->body[3] = cpu_to_le32(i2o_dma_high(c->status_block.phys)); + msg->body[4] = cpu_to_le32(sizeof(i2o_status_block)); /* always 88 bytes */ - i2o_msg_post(c, m); + i2o_msg_post(c, msg); /* Wait for a reply */ timeout = jiffies + I2O_TIMEOUT_STATUS_GET * HZ; @@ -989,8 +952,7 @@ int i2o_status_get(struct i2o_controller *c) return -ETIMEDOUT; } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout_uninterruptible(1); } #ifdef DEBUG @@ -1007,7 +969,7 @@ int i2o_status_get(struct i2o_controller *c) * The HRT contains information about possible hidden devices but is * mostly useless to us. * - * Returns 0 on success or negativer error code on failure. + * Returns 0 on success or negative error code on failure. */ static int i2o_hrt_get(struct i2o_controller *c) { @@ -1018,20 +980,20 @@ static int i2o_hrt_get(struct i2o_controller *c) struct device *dev = &c->pdev->dev; for (i = 0; i < I2O_HRT_GET_TRIES; i++) { - struct i2o_message __iomem *msg; - u32 m; + struct i2o_message *msg; - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -ETIMEDOUT; + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); - writel(SIX_WORD_MSG_SIZE | SGL_OFFSET_4, &msg->u.head[0]); - writel(I2O_CMD_HRT_GET << 24 | HOST_TID << 12 | ADAPTER_TID, - &msg->u.head[1]); - writel(0xd0000000 | c->hrt.len, &msg->body[0]); - writel(c->hrt.phys, &msg->body[1]); + msg->u.head[0] = cpu_to_le32(SIX_WORD_MSG_SIZE | SGL_OFFSET_4); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_HRT_GET << 24 | HOST_TID << 12 | + ADAPTER_TID); + msg->body[0] = cpu_to_le32(0xd0000000 | c->hrt.len); + msg->body[1] = cpu_to_le32(c->hrt.phys); - rc = i2o_msg_post_wait_mem(c, m, 20, &c->hrt); + rc = i2o_msg_post_wait_mem(c, msg, 20, &c->hrt); if (rc < 0) { osm_err("%s: Unable to get HRT (status=%#x)\n", c->name, @@ -1041,7 +1003,7 @@ static int i2o_hrt_get(struct i2o_controller *c) size = hrt->num_entries * hrt->entry_len << 2; if (size > c->hrt.len) { - if (i2o_dma_realloc(dev, &c->hrt, size, GFP_KERNEL)) + if (i2o_dma_realloc(dev, &c->hrt, size)) return -ENOMEM; else hrt = c->hrt.virt; @@ -1056,15 +1018,6 @@ static int i2o_hrt_get(struct i2o_controller *c) } /** - * i2o_iop_free - Free the i2o_controller struct - * @c: I2O controller to free - */ -void i2o_iop_free(struct i2o_controller *c) -{ - kfree(c); -}; - -/** * i2o_iop_release - release the memory for a I2O controller * @dev: I2O controller which should be released * @@ -1078,14 +1031,11 @@ static void i2o_iop_release(struct device *dev) i2o_iop_free(c); }; -/* I2O controller class */ -static struct class *i2o_controller_class; - /** * i2o_iop_alloc - Allocate and initialize a i2o_controller struct * * Allocate the necessary memory for a i2o_controller struct and - * initialize the lists. + * initialize the lists and message mempool. * * Returns a pointer to the I2O controller or a negative error code on * failure. @@ -1094,26 +1044,35 @@ struct i2o_controller *i2o_iop_alloc(void) { static int unit = 0; /* 0 and 1 are NULL IOP and Local Host */ struct i2o_controller *c; + char poolname[32]; - c = kmalloc(sizeof(*c), GFP_KERNEL); + c = kzalloc(sizeof(*c), GFP_KERNEL); if (!c) { osm_err("i2o: Insufficient memory to allocate a I2O controller." "\n"); return ERR_PTR(-ENOMEM); } - memset(c, 0, sizeof(*c)); - INIT_LIST_HEAD(&c->devices); - spin_lock_init(&c->lock); - init_MUTEX(&c->lct_lock); c->unit = unit++; sprintf(c->name, "iop%d", c->unit); + snprintf(poolname, sizeof(poolname), "i2o_%s_msg_inpool", c->name); + if (i2o_pool_alloc + (&c->in_msg, poolname, I2O_INBOUND_MSG_FRAME_SIZE * 4 + sizeof(u32), + I2O_MSG_INPOOL_MIN)) { + kfree(c); + return ERR_PTR(-ENOMEM); + }; + + INIT_LIST_HEAD(&c->devices); + spin_lock_init(&c->lock); + mutex_init(&c->lct_lock); + device_initialize(&c->device); c->device.release = &i2o_iop_release; - snprintf(c->device.bus_id, BUS_ID_SIZE, "iop%d", c->unit); + dev_set_name(&c->device, "iop%d", c->unit); #if BITS_PER_LONG == 64 spin_lock_init(&c->context_list_lock); @@ -1142,36 +1101,29 @@ int i2o_iop_add(struct i2o_controller *c) goto iop_reset; } - c->classdev = class_device_create(i2o_controller_class, NULL, MKDEV(0,0), - &c->device, "iop%d", c->unit); - if (IS_ERR(c->classdev)) { - osm_err("%s: could not add controller class\n", c->name); - goto device_del; - } - osm_info("%s: Activating I2O controller...\n", c->name); osm_info("%s: This may take a few minutes if there are many devices\n", c->name); if ((rc = i2o_iop_activate(c))) { osm_err("%s: could not activate controller\n", c->name); - goto class_del; + goto device_del; } osm_debug("%s: building sys table...\n", c->name); if ((rc = i2o_systab_build())) - goto class_del; + goto device_del; osm_debug("%s: online controller...\n", c->name); if ((rc = i2o_iop_online(c))) - goto class_del; + goto device_del; osm_debug("%s: getting LCT...\n", c->name); if ((rc = i2o_exec_lct_get(c))) - goto class_del; + goto device_del; list_add(&c->list, &i2o_controllers); @@ -1181,9 +1133,6 @@ int i2o_iop_add(struct i2o_controller *c) return 0; - class_del: - class_device_unregister(c->classdev); - device_del: device_del(&c->device); @@ -1204,28 +1153,27 @@ int i2o_iop_add(struct i2o_controller *c) * is waited for, or expected. If you do not want further notifications, * call the i2o_event_register again with a evt_mask of 0. * - * Returns 0 on success or -ETIMEDOUT if no message could be fetched for - * sending the request. + * Returns 0 on success or negative error code on failure. */ int i2o_event_register(struct i2o_device *dev, struct i2o_driver *drv, int tcntxt, u32 evt_mask) { struct i2o_controller *c = dev->iop; - struct i2o_message __iomem *msg; - u32 m; + struct i2o_message *msg; - m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); - if (m == I2O_QUEUE_EMPTY) - return -ETIMEDOUT; + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); - writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); - writel(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | dev->lct_data. - tid, &msg->u.head[1]); - writel(drv->context, &msg->u.s.icntxt); - writel(tcntxt, &msg->u.s.tcntxt); - writel(evt_mask, &msg->body[0]); + msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | dev-> + lct_data.tid); + msg->u.s.icntxt = cpu_to_le32(drv->context); + msg->u.s.tcntxt = cpu_to_le32(tcntxt); + msg->body[0] = cpu_to_le32(evt_mask); - i2o_msg_post(c, m); + i2o_msg_post(c, msg); return 0; }; @@ -1244,14 +1192,8 @@ static int __init i2o_iop_init(void) printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n"); - i2o_controller_class = class_create(THIS_MODULE, "i2o_controller"); - if (IS_ERR(i2o_controller_class)) { - osm_err("can't register class i2o_controller\n"); - goto exit; - } - if ((rc = i2o_driver_init())) - goto class_exit; + goto exit; if ((rc = i2o_exec_init())) goto driver_exit; @@ -1267,9 +1209,6 @@ static int __init i2o_iop_init(void) driver_exit: i2o_driver_exit(); - class_exit: - class_destroy(i2o_controller_class); - exit: return rc; } @@ -1284,7 +1223,6 @@ static void __exit i2o_iop_exit(void) i2o_pci_exit(); i2o_exec_exit(); i2o_driver_exit(); - class_destroy(i2o_controller_class); }; module_init(i2o_iop_init); @@ -1302,7 +1240,6 @@ EXPORT_SYMBOL(i2o_cntxt_list_remove); EXPORT_SYMBOL(i2o_cntxt_list_get_ptr); #endif EXPORT_SYMBOL(i2o_msg_get_wait); -EXPORT_SYMBOL(i2o_msg_nop); EXPORT_SYMBOL(i2o_find_iop); EXPORT_SYMBOL(i2o_iop_find_device); EXPORT_SYMBOL(i2o_event_register); diff --git a/drivers/message/i2o/memory.c b/drivers/message/i2o/memory.c new file mode 100644 index 00000000000..292b41e49fb --- /dev/null +++ b/drivers/message/i2o/memory.c @@ -0,0 +1,313 @@ +/* + * Functions to handle I2O memory + * + * Pulled from the inlines in i2o headers and uninlined + * + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/module.h> +#include <linux/i2o.h> +#include <linux/delay.h> +#include <linux/string.h> +#include <linux/slab.h> +#include "core.h" + +/* Protects our 32/64bit mask switching */ +static DEFINE_MUTEX(mem_lock); + +/** + * i2o_sg_tablesize - Calculate the maximum number of elements in a SGL + * @c: I2O controller for which the calculation should be done + * @body_size: maximum body size used for message in 32-bit words. + * + * Return the maximum number of SG elements in a SG list. + */ +u16 i2o_sg_tablesize(struct i2o_controller *c, u16 body_size) +{ + i2o_status_block *sb = c->status_block.virt; + u16 sg_count = + (sb->inbound_frame_size - sizeof(struct i2o_message) / 4) - + body_size; + + if (c->pae_support) { + /* + * for 64-bit a SG attribute element must be added and each + * SG element needs 12 bytes instead of 8. + */ + sg_count -= 2; + sg_count /= 3; + } else + sg_count /= 2; + + if (c->short_req && (sg_count > 8)) + sg_count = 8; + + return sg_count; +} +EXPORT_SYMBOL_GPL(i2o_sg_tablesize); + + +/** + * i2o_dma_map_single - Map pointer to controller and fill in I2O message. + * @c: I2O controller + * @ptr: pointer to the data which should be mapped + * @size: size of data in bytes + * @direction: DMA_TO_DEVICE / DMA_FROM_DEVICE + * @sg_ptr: pointer to the SG list inside the I2O message + * + * This function does all necessary DMA handling and also writes the I2O + * SGL elements into the I2O message. For details on DMA handling see also + * dma_map_single(). The pointer sg_ptr will only be set to the end of the + * SG list if the allocation was successful. + * + * Returns DMA address which must be checked for failures using + * dma_mapping_error(). + */ +dma_addr_t i2o_dma_map_single(struct i2o_controller *c, void *ptr, + size_t size, + enum dma_data_direction direction, + u32 ** sg_ptr) +{ + u32 sg_flags; + u32 *mptr = *sg_ptr; + dma_addr_t dma_addr; + + switch (direction) { + case DMA_TO_DEVICE: + sg_flags = 0xd4000000; + break; + case DMA_FROM_DEVICE: + sg_flags = 0xd0000000; + break; + default: + return 0; + } + + dma_addr = dma_map_single(&c->pdev->dev, ptr, size, direction); + if (!dma_mapping_error(&c->pdev->dev, dma_addr)) { +#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 + if ((sizeof(dma_addr_t) > 4) && c->pae_support) { + *mptr++ = cpu_to_le32(0x7C020002); + *mptr++ = cpu_to_le32(PAGE_SIZE); + } +#endif + + *mptr++ = cpu_to_le32(sg_flags | size); + *mptr++ = cpu_to_le32(i2o_dma_low(dma_addr)); +#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 + if ((sizeof(dma_addr_t) > 4) && c->pae_support) + *mptr++ = cpu_to_le32(i2o_dma_high(dma_addr)); +#endif + *sg_ptr = mptr; + } + return dma_addr; +} +EXPORT_SYMBOL_GPL(i2o_dma_map_single); + +/** + * i2o_dma_map_sg - Map a SG List to controller and fill in I2O message. + * @c: I2O controller + * @sg: SG list to be mapped + * @sg_count: number of elements in the SG list + * @direction: DMA_TO_DEVICE / DMA_FROM_DEVICE + * @sg_ptr: pointer to the SG list inside the I2O message + * + * This function does all necessary DMA handling and also writes the I2O + * SGL elements into the I2O message. For details on DMA handling see also + * dma_map_sg(). The pointer sg_ptr will only be set to the end of the SG + * list if the allocation was successful. + * + * Returns 0 on failure or 1 on success. + */ +int i2o_dma_map_sg(struct i2o_controller *c, struct scatterlist *sg, + int sg_count, enum dma_data_direction direction, u32 ** sg_ptr) +{ + u32 sg_flags; + u32 *mptr = *sg_ptr; + + switch (direction) { + case DMA_TO_DEVICE: + sg_flags = 0x14000000; + break; + case DMA_FROM_DEVICE: + sg_flags = 0x10000000; + break; + default: + return 0; + } + + sg_count = dma_map_sg(&c->pdev->dev, sg, sg_count, direction); + if (!sg_count) + return 0; + +#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 + if ((sizeof(dma_addr_t) > 4) && c->pae_support) { + *mptr++ = cpu_to_le32(0x7C020002); + *mptr++ = cpu_to_le32(PAGE_SIZE); + } +#endif + + while (sg_count-- > 0) { + if (!sg_count) + sg_flags |= 0xC0000000; + *mptr++ = cpu_to_le32(sg_flags | sg_dma_len(sg)); + *mptr++ = cpu_to_le32(i2o_dma_low(sg_dma_address(sg))); +#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 + if ((sizeof(dma_addr_t) > 4) && c->pae_support) + *mptr++ = cpu_to_le32(i2o_dma_high(sg_dma_address(sg))); +#endif + sg = sg_next(sg); + } + *sg_ptr = mptr; + + return 1; +} +EXPORT_SYMBOL_GPL(i2o_dma_map_sg); + +/** + * i2o_dma_alloc - Allocate DMA memory + * @dev: struct device pointer to the PCI device of the I2O controller + * @addr: i2o_dma struct which should get the DMA buffer + * @len: length of the new DMA memory + * + * Allocate a coherent DMA memory and write the pointers into addr. + * + * Returns 0 on success or -ENOMEM on failure. + */ +int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr, size_t len) +{ + struct pci_dev *pdev = to_pci_dev(dev); + int dma_64 = 0; + + mutex_lock(&mem_lock); + if ((sizeof(dma_addr_t) > 4) && (pdev->dma_mask == DMA_BIT_MASK(64))) { + dma_64 = 1; + if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { + mutex_unlock(&mem_lock); + return -ENOMEM; + } + } + + addr->virt = dma_alloc_coherent(dev, len, &addr->phys, GFP_KERNEL); + + if ((sizeof(dma_addr_t) > 4) && dma_64) + if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) + printk(KERN_WARNING "i2o: unable to set 64-bit DMA"); + mutex_unlock(&mem_lock); + + if (!addr->virt) + return -ENOMEM; + + memset(addr->virt, 0, len); + addr->len = len; + + return 0; +} +EXPORT_SYMBOL_GPL(i2o_dma_alloc); + + +/** + * i2o_dma_free - Free DMA memory + * @dev: struct device pointer to the PCI device of the I2O controller + * @addr: i2o_dma struct which contains the DMA buffer + * + * Free a coherent DMA memory and set virtual address of addr to NULL. + */ +void i2o_dma_free(struct device *dev, struct i2o_dma *addr) +{ + if (addr->virt) { + if (addr->phys) + dma_free_coherent(dev, addr->len, addr->virt, + addr->phys); + else + kfree(addr->virt); + addr->virt = NULL; + } +} +EXPORT_SYMBOL_GPL(i2o_dma_free); + + +/** + * i2o_dma_realloc - Realloc DMA memory + * @dev: struct device pointer to the PCI device of the I2O controller + * @addr: pointer to a i2o_dma struct DMA buffer + * @len: new length of memory + * + * If there was something allocated in the addr, free it first. If len > 0 + * than try to allocate it and write the addresses back to the addr + * structure. If len == 0 set the virtual address to NULL. + * + * Returns the 0 on success or negative error code on failure. + */ +int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr, size_t len) +{ + i2o_dma_free(dev, addr); + + if (len) + return i2o_dma_alloc(dev, addr, len); + + return 0; +} +EXPORT_SYMBOL_GPL(i2o_dma_realloc); + +/* + * i2o_pool_alloc - Allocate an slab cache and mempool + * @mempool: pointer to struct i2o_pool to write data into. + * @name: name which is used to identify cache + * @size: size of each object + * @min_nr: minimum number of objects + * + * First allocates a slab cache with name and size. Then allocates a + * mempool which uses the slab cache for allocation and freeing. + * + * Returns 0 on success or negative error code on failure. + */ +int i2o_pool_alloc(struct i2o_pool *pool, const char *name, + size_t size, int min_nr) +{ + pool->name = kmalloc(strlen(name) + 1, GFP_KERNEL); + if (!pool->name) + goto exit; + strcpy(pool->name, name); + + pool->slab = + kmem_cache_create(pool->name, size, 0, SLAB_HWCACHE_ALIGN, NULL); + if (!pool->slab) + goto free_name; + + pool->mempool = mempool_create_slab_pool(min_nr, pool->slab); + if (!pool->mempool) + goto free_slab; + + return 0; + +free_slab: + kmem_cache_destroy(pool->slab); + +free_name: + kfree(pool->name); + +exit: + return -ENOMEM; +} +EXPORT_SYMBOL_GPL(i2o_pool_alloc); + +/* + * i2o_pool_free - Free slab cache and mempool again + * @mempool: pointer to struct i2o_pool which should be freed + * + * Note that you have to return all objects to the mempool again before + * calling i2o_pool_free(). + */ +void i2o_pool_free(struct i2o_pool *pool) +{ + mempool_destroy(pool->mempool); + kmem_cache_destroy(pool->slab); + kfree(pool->name); +}; +EXPORT_SYMBOL_GPL(i2o_pool_free); diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c index 66c03e88257..0f9f3e1a2b6 100644 --- a/drivers/message/i2o/pci.c +++ b/drivers/message/i2o/pci.c @@ -15,11 +15,11 @@ * * Fixes/additions: * Philipp Rumpf - * Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI> - * Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI> + * Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI> + * Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI> * Deepak Saxena <deepak@plexity.net> * Boji T Kannanthanam <boji.t.kannanthanam@intel.com> - * Alan Cox <alan@redhat.com>: + * Alan Cox <alan@lxorguk.ukuu.org.uk>: * Ported to Linux 2.5. * Markus Lidel <Markus.Lidel@shadowconnect.com>: * Minor fixes for 2.6. @@ -29,13 +29,15 @@ #include <linux/pci.h> #include <linux/interrupt.h> +#include <linux/slab.h> #include <linux/i2o.h> +#include <linux/module.h> #include "core.h" #define OSM_DESCRIPTION "I2O-subsystem" /* PCI device id table for all I2O controllers */ -static struct pci_device_id __devinitdata i2o_pci_ids[] = { +static struct pci_device_id i2o_pci_ids[] = { {PCI_DEVICE_CLASS(PCI_CLASS_INTELLIGENT_I2O << 8, 0xffff00)}, {PCI_DEVICE(PCI_VENDOR_ID_DPT, 0xa511)}, {.vendor = PCI_VENDOR_ID_INTEL,.device = 0x1962, @@ -82,7 +84,7 @@ static void i2o_pci_free(struct i2o_controller *c) * * Returns 0 on success or negative error code on failure. */ -static int __devinit i2o_pci_alloc(struct i2o_controller *c) +static int i2o_pci_alloc(struct i2o_controller *c) { struct pci_dev *pdev = c->pdev; struct device *dev = &pdev->dev; @@ -168,31 +170,47 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) c->in_port = c->base.virt + I2O_IN_PORT; c->out_port = c->base.virt + I2O_OUT_PORT; - if (i2o_dma_alloc(dev, &c->status, 8, GFP_KERNEL)) { + /* Motorola/Freescale chip does not follow spec */ + if (pdev->vendor == PCI_VENDOR_ID_MOTOROLA && pdev->device == 0x18c0) { + /* Check if CPU is enabled */ + if (be32_to_cpu(readl(c->base.virt + 0x10000)) & 0x10000000) { + printk(KERN_INFO "%s: MPC82XX needs CPU running to " + "service I2O.\n", c->name); + i2o_pci_free(c); + return -ENODEV; + } else { + c->irq_status += I2O_MOTOROLA_PORT_OFFSET; + c->irq_mask += I2O_MOTOROLA_PORT_OFFSET; + c->in_port += I2O_MOTOROLA_PORT_OFFSET; + c->out_port += I2O_MOTOROLA_PORT_OFFSET; + printk(KERN_INFO "%s: MPC82XX workarounds activated.\n", + c->name); + } + } + + if (i2o_dma_alloc(dev, &c->status, 8)) { i2o_pci_free(c); return -ENOMEM; } - if (i2o_dma_alloc(dev, &c->hrt, sizeof(i2o_hrt), GFP_KERNEL)) { + if (i2o_dma_alloc(dev, &c->hrt, sizeof(i2o_hrt))) { i2o_pci_free(c); return -ENOMEM; } - if (i2o_dma_alloc(dev, &c->dlct, 8192, GFP_KERNEL)) { + if (i2o_dma_alloc(dev, &c->dlct, 8192)) { i2o_pci_free(c); return -ENOMEM; } - if (i2o_dma_alloc(dev, &c->status_block, sizeof(i2o_status_block), - GFP_KERNEL)) { + if (i2o_dma_alloc(dev, &c->status_block, sizeof(i2o_status_block))) { i2o_pci_free(c); return -ENOMEM; } - if (i2o_dma_alloc - (dev, &c->out_queue, - I2O_MAX_OUTBOUND_MSG_FRAMES * I2O_OUTBOUND_MSG_FRAME_SIZE * - sizeof(u32), GFP_KERNEL)) { + if (i2o_dma_alloc(dev, &c->out_queue, + I2O_MAX_OUTBOUND_MSG_FRAMES * I2O_OUTBOUND_MSG_FRAME_SIZE * + sizeof(u32))) { i2o_pci_free(c); return -ENOMEM; } @@ -206,12 +224,11 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) * i2o_pci_interrupt - Interrupt handler for I2O controller * @irq: interrupt line * @dev_id: pointer to the I2O controller - * @r: pointer to registers * * Handle an interrupt from a PCI based I2O controller. This turns out * to be rather simple. We keep the controller pointer in the cookie. */ -static irqreturn_t i2o_pci_interrupt(int irq, void *dev_id, struct pt_regs *r) +static irqreturn_t i2o_pci_interrupt(int irq, void *dev_id) { struct i2o_controller *c = dev_id; u32 m; @@ -242,6 +259,7 @@ static irqreturn_t i2o_pci_interrupt(int irq, void *dev_id, struct pt_regs *r) /** * i2o_pci_irq_enable - Allocate interrupt for I2O controller + * @c: i2o_controller that the request is for * * Allocate an interrupt for the I2O controller, and activate interrupts * on the I2O controller. @@ -256,7 +274,7 @@ static int i2o_pci_irq_enable(struct i2o_controller *c) writel(0xffffffff, c->irq_mask); if (pdev->irq) { - rc = request_irq(pdev->irq, i2o_pci_interrupt, SA_SHIRQ, + rc = request_irq(pdev->irq, i2o_pci_interrupt, IRQF_SHARED, c->name, c); if (rc < 0) { printk(KERN_ERR "%s: unable to allocate interrupt %d." @@ -288,7 +306,7 @@ static void i2o_pci_irq_disable(struct i2o_controller *c) /** * i2o_pci_probe - Probe the PCI device for an I2O controller - * @dev: PCI device to test + * @pdev: PCI device to test * @id: id which matched with the PCI device id table * * Probe the PCI device for any device which is a memory of the @@ -297,8 +315,7 @@ static void i2o_pci_irq_disable(struct i2o_controller *c) * * Returns 0 on success or negative error code on failure. */ -static int __devinit i2o_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *id) +static int i2o_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct i2o_controller *c; int rc; @@ -318,7 +335,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, return rc; } - if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { + if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { printk(KERN_WARNING "i2o: no suitable DMA found for %s\n", pci_name(pdev)); rc = -ENODEV; @@ -338,7 +355,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, pci_name(pdev)); c->pdev = pdev; - c->device.parent = get_device(&pdev->dev); + c->device.parent = &pdev->dev; /* Cards that fall apart if you hit them with large I/O loads... */ if (pdev->vendor == PCI_VENDOR_ID_NCR && pdev->device == 0x0630) { @@ -352,12 +369,13 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, * Expose the ship behind i960 for initialization, or it will * failed */ - i960 = - pci_find_slot(c->pdev->bus->number, + i960 = pci_get_slot(c->pdev->bus, PCI_DEVFN(PCI_SLOT(c->pdev->devfn), 0)); - if (i960) + if (i960) { pci_write_config_word(i960, 0x42, 0); + pci_dev_put(i960); + } c->promise = 1; c->limit_sectors = 1; @@ -380,7 +398,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, } #ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 if (sizeof(dma_addr_t) > 4) { - if (pci_set_dma_mask(pdev, DMA_64BIT_MASK)) + if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) printk(KERN_INFO "%s: 64-bit DMA unavailable\n", c->name); else { @@ -394,7 +412,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, if ((rc = i2o_pci_alloc(c))) { printk(KERN_ERR "%s: DMA / IO allocation for I2O controller " - " failed\n", c->name); + "failed\n", c->name); goto free_controller; } @@ -407,8 +425,6 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, if ((rc = i2o_iop_add(c))) goto uninstall; - get_device(&c->device); - if (i960) pci_write_config_word(i960, 0x42, 0x03ff); @@ -422,7 +438,6 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, free_controller: i2o_iop_free(c); - put_device(c->device.parent); disable: pci_disable_device(pdev); @@ -432,12 +447,12 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, /** * i2o_pci_remove - Removes a I2O controller from the system - * pdev: I2O controller which should be removed + * @pdev: I2O controller which should be removed * * Reset the I2O controller, disable interrupts and remove all allocated * resources. */ -static void __devexit i2o_pci_remove(struct pci_dev *pdev) +static void i2o_pci_remove(struct pci_dev *pdev) { struct i2o_controller *c; c = pci_get_drvdata(pdev); @@ -450,7 +465,6 @@ static void __devexit i2o_pci_remove(struct pci_dev *pdev) printk(KERN_INFO "%s: Controller removed.\n", c->name); - put_device(c->device.parent); put_device(&c->device); }; @@ -459,7 +473,7 @@ static struct pci_driver i2o_pci_driver = { .name = "PCI_I2O", .id_table = i2o_pci_ids, .probe = i2o_pci_probe, - .remove = __devexit_p(i2o_pci_remove), + .remove = i2o_pci_remove, }; /** @@ -479,4 +493,5 @@ void __exit i2o_pci_exit(void) { pci_unregister_driver(&i2o_pci_driver); }; + MODULE_DEVICE_TABLE(pci, i2o_pci_ids); |
